mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
Merge branch 'develop' into ismail/5068_start_thread
This commit is contained in:
commit
8cc82cf7e1
114 changed files with 2639 additions and 548 deletions
5
.github/ISSUE_TEMPLATE/bug.yml
vendored
5
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -57,8 +57,9 @@ body:
|
|||
id: homeserver
|
||||
attributes:
|
||||
label: Homeserver
|
||||
description: Which server is your account registered on?
|
||||
placeholder: e.g. matrix.org
|
||||
description: |
|
||||
Which server is your account registered on? If it is a local or non-public homeserver, please tell us what is the homeserver implementation (ex: Synapse/Dendrite/etc.) and the version.
|
||||
placeholder: e.g. matrix.org or Synapse 1.50.0rc1
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
|
|
1
.github/workflows/ci-build.yml
vendored
1
.github/workflows/ci-build.yml
vendored
|
@ -11,7 +11,6 @@ on:
|
|||
env:
|
||||
# Make the git branch for a PR available to our Fastfile
|
||||
MX_GIT_BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||
MapTilerAPIKey: ${{ secrets.MAPTILER_API_KEY }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
1
.github/workflows/ci-tests.yml
vendored
1
.github/workflows/ci-tests.yml
vendored
|
@ -12,7 +12,6 @@ on:
|
|||
env:
|
||||
# Make the git branch for a PR available to our Fastfile
|
||||
MX_GIT_BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||
MapTilerAPIKey: ${{ secrets.MAPTILER_API_KEY }}
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
|
|
1
.github/workflows/release-alpha.yml
vendored
1
.github/workflows/release-alpha.yml
vendored
|
@ -11,7 +11,6 @@ on:
|
|||
env:
|
||||
# Make the git branch for a PR available to our Fastfile
|
||||
MX_GIT_BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||
MapTilerAPIKey: ${{ secrets.MAPTILER_API_KEY }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import Keys
|
||||
|
||||
/// BuildSettings provides settings computed at build time.
|
||||
/// In future, it may be automatically generated from xcconfig files
|
||||
|
@ -213,7 +212,9 @@ final class BuildSettings: NSObject {
|
|||
|
||||
static let allowInviteExernalUsers: Bool = true
|
||||
|
||||
// MARK: - Side Menu
|
||||
static let enableSideMenu: Bool = true
|
||||
static let sideMenuShowInviteFriends: Bool = true
|
||||
|
||||
/// Whether to read the `io.element.functional_members` state event and exclude any service members when computing a room's name and avatar.
|
||||
static let supportFunctionalMembers: Bool = true
|
||||
|
@ -261,7 +262,6 @@ final class BuildSettings: NSObject {
|
|||
static let settingsScreenAllowBugReportingManually: Bool = true
|
||||
static let settingsScreenAllowDeactivatingAccount: Bool = true
|
||||
static let settingsScreenShowChangePassword:Bool = true
|
||||
static let settingsScreenShowInviteFriends:Bool = true
|
||||
static let settingsScreenShowEnableStunServerFallback: Bool = true
|
||||
static let settingsScreenShowNotificationDecodedContentOption: Bool = true
|
||||
static let settingsScreenShowNsfwRoomsOption: Bool = true
|
||||
|
@ -349,6 +349,7 @@ final class BuildSettings: NSObject {
|
|||
static let authScreenShowPhoneNumber = true
|
||||
static let authScreenShowForgotPassword = true
|
||||
static let authScreenShowCustomServerOptions = true
|
||||
static let authScreenShowSocialLoginSection = true
|
||||
|
||||
// MARK: - Unified Search
|
||||
static let unifiedSearchScreenShowPublicDirectory = true
|
||||
|
@ -368,7 +369,7 @@ final class BuildSettings: NSObject {
|
|||
|
||||
// MARK: - Location Sharing
|
||||
|
||||
static let tileServerMapURL = URL(string: "https://api.maptiler.com/maps/streets/style.json?key=" + RiotKeys().mapTilerAPIKey)!
|
||||
static let tileServerMapURL = URL(string: "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx")!
|
||||
|
||||
static var locationSharingEnabled: Bool {
|
||||
guard #available(iOS 14, *) else {
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -3,7 +3,6 @@ source "https://rubygems.org"
|
|||
gem "xcode-install"
|
||||
gem "fastlane"
|
||||
gem "cocoapods", '~>1.11.2'
|
||||
gem "cocoapods-keys"
|
||||
|
||||
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
|
||||
eval_gemfile(plugins_path) if File.exist?(plugins_path)
|
||||
|
|
11
Gemfile.lock
11
Gemfile.lock
|
@ -3,9 +3,6 @@ GEM
|
|||
specs:
|
||||
CFPropertyList (3.0.5)
|
||||
rexml
|
||||
RubyInline (3.12.5)
|
||||
ZenTest (~> 4.3)
|
||||
ZenTest (4.12.0)
|
||||
activesupport (6.1.4.4)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
|
@ -67,9 +64,6 @@ GEM
|
|||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.5)
|
||||
cocoapods-downloader (1.5.1)
|
||||
cocoapods-keys (2.2.1)
|
||||
dotenv
|
||||
osx_keychain
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.1)
|
||||
|
@ -231,8 +225,6 @@ GEM
|
|||
netrc (0.11.0)
|
||||
optparse (0.1.1)
|
||||
os (1.1.4)
|
||||
osx_keychain (1.0.2)
|
||||
RubyInline (~> 3)
|
||||
plist (3.6.0)
|
||||
public_suffix (4.0.6)
|
||||
rake (13.0.6)
|
||||
|
@ -300,7 +292,6 @@ PLATFORMS
|
|||
|
||||
DEPENDENCIES
|
||||
cocoapods (~> 1.11.2)
|
||||
cocoapods-keys
|
||||
fastlane
|
||||
fastlane-plugin-diawi
|
||||
fastlane-plugin-versioning
|
||||
|
@ -308,4 +299,4 @@ DEPENDENCIES
|
|||
xcode-install
|
||||
|
||||
BUNDLED WITH
|
||||
2.2.28
|
||||
2.2.32
|
||||
|
|
5
Podfile
5
Podfile
|
@ -129,11 +129,6 @@ abstract_target 'RiotPods' do
|
|||
|
||||
end
|
||||
|
||||
plugin 'cocoapods-keys', {
|
||||
:project => "Riot",
|
||||
:keys => ["MapTilerAPIKey"]
|
||||
}
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ PODS:
|
|||
- Introspect (0.1.3)
|
||||
- JitsiMeetSDK (3.10.2)
|
||||
- KeychainAccess (4.2.2)
|
||||
- Keys (1.0.1)
|
||||
- KituraContracts (1.2.1):
|
||||
- LoggerAPI (~> 1.7)
|
||||
- KTCenterFlowLayout (1.3.1)
|
||||
|
@ -115,7 +114,6 @@ DEPENDENCIES:
|
|||
- HPGrowingTextView (~> 1.1)
|
||||
- Introspect (~> 0.1)
|
||||
- KeychainAccess (~> 4.2.2)
|
||||
- Keys (from `Pods/CocoaPodsKeys`)
|
||||
- KTCenterFlowLayout (~> 1.3.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixSDK (= 0.20.16)
|
||||
|
@ -179,12 +177,10 @@ EXTERNAL SOURCES:
|
|||
AnalyticsEvents:
|
||||
:branch: release/swift
|
||||
:git: https://github.com/matrix-org/matrix-analytics-events.git
|
||||
Keys:
|
||||
:path: Pods/CocoaPodsKeys
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
AnalyticsEvents:
|
||||
:commit: f1805ad7c3fafa7fd9c6e2eaa9e0165f8142ecd2
|
||||
:commit: 8058dc6ec07ce0acfe5fdb19eb7e309b0c13845c
|
||||
:git: https://github.com/matrix-org/matrix-analytics-events.git
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
|
@ -207,7 +203,6 @@ SPEC CHECKSUMS:
|
|||
Introspect: 2be020f30f084ada52bb4387fff83fa52c5c400e
|
||||
JitsiMeetSDK: 2f118fa770f23e518f3560fc224fae3ac7062223
|
||||
KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
|
||||
Keys: a576f4c9c1c641ca913a959a9c62ed3f215a8de9
|
||||
KituraContracts: e845e60dc8627ad0a76fa55ef20a45451d8f830b
|
||||
KTCenterFlowLayout: 6e02b50ab2bd865025ae82fe266ed13b6d9eaf97
|
||||
libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd
|
||||
|
@ -230,6 +225,6 @@ SPEC CHECKSUMS:
|
|||
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
|
||||
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
||||
|
||||
PODFILE CHECKSUM: 2493587902f8f28bb2638303dd583c47e9f24d8b
|
||||
PODFILE CHECKSUM: c9a50c445e32b40b22fadd0f54b376f1bd624ebb
|
||||
|
||||
COCOAPODS: 1.11.2
|
||||
|
|
|
@ -19,5 +19,8 @@
|
|||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
|
|
33
Riot/Categories/MXKRoomBubbleCellData+Riot.swift
Normal file
33
Riot/Categories/MXKRoomBubbleCellData+Riot.swift
Normal file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
extension MXKRoomBubbleCellData {
|
||||
|
||||
/// Indicate true if the sender is the session user
|
||||
var isSenderCurrentUser: Bool {
|
||||
if let senderId = self.senderId, let currentUserId = self.mxSession.myUserId, senderId == currentUserId {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Indicate true if the cell data is collapsable and collapsed
|
||||
var isCollapsableAndCollapsed: Bool {
|
||||
return self.collapsable && self.collapsed
|
||||
}
|
||||
}
|
|
@ -198,6 +198,10 @@ final class RiotSettings: NSObject {
|
|||
@UserDefault(key: "roomScreenEnableMessageBubbles", defaultValue: BuildSettings.roomScreenEnableMessageBubblesByDefault, storage: defaults)
|
||||
var roomScreenEnableMessageBubbles
|
||||
|
||||
var roomTimelineStyleIdentifier: RoomTimelineStyleIdentifier {
|
||||
return self.roomScreenEnableMessageBubbles ? .bubble : .plain
|
||||
}
|
||||
|
||||
// MARK: - Room Contextual Menu
|
||||
|
||||
@UserDefault(key: "roomContextualMenuShowMoreOptionForMessages", defaultValue: BuildSettings.roomContextualMenuShowMoreOptionForMessages, storage: defaults)
|
||||
|
|
|
@ -52,7 +52,7 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChan
|
|||
|
||||
[self updateAppearance];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kThemeServiceDidChangeThemeNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kThemeServiceDidChangeThemeNotification object:self];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1391,9 +1391,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
else
|
||||
{
|
||||
void(^findRoom)(void) = ^{
|
||||
if ([_masterTabBarController.selectedViewController isKindOfClass:MXKActivityHandlingViewController.class])
|
||||
if ([_masterTabBarController.selectedViewController conformsToProtocol:@protocol(MXKViewControllerActivityHandling)])
|
||||
{
|
||||
MXKActivityHandlingViewController *homeViewController = (MXKActivityHandlingViewController*)_masterTabBarController.selectedViewController;
|
||||
UIViewController<MXKViewControllerActivityHandling> *homeViewController = (UIViewController<MXKViewControllerActivityHandling>*)_masterTabBarController.selectedViewController;
|
||||
|
||||
[homeViewController startActivityIndicator];
|
||||
|
||||
|
@ -1670,11 +1670,13 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
// Try to get more information about the room before opening its preview
|
||||
[roomPreviewData peekInRoom:^(BOOL succeeded) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
MXKViewController *homeViewController = (MXKViewController*)self.masterTabBarController.selectedViewController;
|
||||
if ([self.masterTabBarController.selectedViewController conformsToProtocol:@protocol(MXKViewControllerActivityHandling)])
|
||||
{
|
||||
UIViewController<MXKViewControllerActivityHandling> *homeViewController = (UIViewController<MXKViewControllerActivityHandling>*)self.masterTabBarController.selectedViewController;
|
||||
|
||||
// Note: the activity indicator will not disappear if the session is not ready
|
||||
[homeViewController stopActivityIndicator];
|
||||
}
|
||||
|
||||
// If no data is available for this room, we name it with the known room alias (if any).
|
||||
if (!succeeded && self->universalLinkFragmentPendingRoomAlias[roomIdOrAlias])
|
||||
|
|
|
@ -482,7 +482,8 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
|
|||
// Hide input view when there is only social login actions to present
|
||||
if ((self.authType == MXKAuthenticationTypeLogin || self.authType == MXKAuthenticationTypeRegister)
|
||||
&& self.currentLoginSSOFlow
|
||||
&& !self.isAuthSessionContainsPasswordFlow)
|
||||
&& !self.isAuthSessionContainsPasswordFlow
|
||||
&& BuildSettings.authScreenShowSocialLoginSection)
|
||||
{
|
||||
hideAuthInputView = YES;
|
||||
}
|
||||
|
@ -1736,7 +1737,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
|
|||
{
|
||||
SocialLoginButtonMode socialLoginButtonMode = SocialLoginButtonModeContinue;
|
||||
|
||||
BOOL showSocialLoginView = self.currentLoginSSOFlow ? YES : NO;
|
||||
BOOL showSocialLoginView = BuildSettings.authScreenShowSocialLoginSection && (self.currentLoginSSOFlow ? YES : NO);
|
||||
|
||||
switch (self.authType)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
/// UICollectionViewFlowLayout with right align behavior
|
||||
class CollectionViewRightAlignFlowLayout: UICollectionViewFlowLayout {
|
||||
|
||||
override var flipsHorizontallyInOppositeLayoutDirection: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override var developmentLayoutDirection: UIUserInterfaceLayoutDirection {
|
||||
return UIUserInterfaceLayoutDirection.rightToLeft
|
||||
}
|
||||
}
|
|
@ -1026,6 +1026,12 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
|||
{
|
||||
[super dataSource:dataSource didCellChange:changes];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Since we've enabled room list pagination, `refreshRecentsTable` not called in this case.
|
||||
// Refresh tab bar badges separately.
|
||||
[[AppDelegate theDelegate].masterTabBarController refreshTabBarBadges];
|
||||
}
|
||||
|
||||
if (changes == nil)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class HomeViewControllerWithBannerWrapperViewController: MXKActivityHandlingViewController, BannerPresentationProtocol {
|
||||
class HomeViewControllerWithBannerWrapperViewController: UIViewController, MXKViewControllerActivityHandling, BannerPresentationProtocol {
|
||||
|
||||
@objc let homeViewController: HomeViewController
|
||||
private var bannerContainerView: UIView!
|
||||
|
@ -85,4 +85,22 @@ class HomeViewControllerWithBannerWrapperViewController: MXKActivityHandlingView
|
|||
bannerView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MXKViewControllerActivityHandling
|
||||
var activityIndicator: UIActivityIndicatorView! {
|
||||
get {
|
||||
return homeViewController.activityIndicator
|
||||
}
|
||||
set {
|
||||
homeViewController.activityIndicator = newValue
|
||||
}
|
||||
}
|
||||
|
||||
func startActivityIndicator() {
|
||||
homeViewController.startActivityIndicator()
|
||||
}
|
||||
|
||||
func stopActivityIndicator() {
|
||||
homeViewController.stopActivityIndicator()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,3 +14,4 @@
|
|||
|
||||
#import "MXKRoomInputToolbarView.h"
|
||||
#import "MXKImageView.h"
|
||||
#import "MXKRoomBubbleCellData.h"
|
||||
|
|
|
@ -168,4 +168,11 @@
|
|||
*/
|
||||
- (MXKRoomBubbleComponent*)getFirstBubbleComponentWithDisplay;
|
||||
|
||||
/**
|
||||
Get the last visible component.
|
||||
|
||||
@return Last visible component or nil.
|
||||
*/
|
||||
- (MXKRoomBubbleComponent*)getLastBubbleComponentWithDisplay;
|
||||
|
||||
@end
|
||||
|
|
|
@ -313,9 +313,8 @@
|
|||
|
||||
@synchronized(bubbleComponents)
|
||||
{
|
||||
for (NSInteger index = 0; index < bubbleComponents.count; index++)
|
||||
for (MXKRoomBubbleComponent *component in bubbleComponents)
|
||||
{
|
||||
MXKRoomBubbleComponent *component = bubbleComponents[index];
|
||||
if (component.attributedTextMessage)
|
||||
{
|
||||
first = component;
|
||||
|
@ -327,6 +326,26 @@
|
|||
return first;
|
||||
}
|
||||
|
||||
- (MXKRoomBubbleComponent*)getLastBubbleComponentWithDisplay
|
||||
{
|
||||
// Look for the first component which is actually displayed (some event are ignored in room history display).
|
||||
MXKRoomBubbleComponent* lastVisibleComponent = nil;
|
||||
|
||||
@synchronized(bubbleComponents)
|
||||
{
|
||||
for (MXKRoomBubbleComponent *component in bubbleComponents.reverseObjectEnumerator)
|
||||
{
|
||||
if (component.attributedTextMessage)
|
||||
{
|
||||
lastVisibleComponent = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lastVisibleComponent;
|
||||
}
|
||||
|
||||
- (NSAttributedString*)attributedTextMessageWithHighlightedEvent:(NSString*)eventId tintColor:(UIColor*)tintColor
|
||||
{
|
||||
NSAttributedString *customAttributedTextMsg;
|
||||
|
|
|
@ -18,6 +18,13 @@ import Foundation
|
|||
import MatrixSDK
|
||||
import Reusable
|
||||
import DGCollectionViewLeftAlignFlowLayout
|
||||
import UIKit
|
||||
|
||||
/// BubbleReactionsView items alignment
|
||||
enum BubbleReactionsViewAlignment {
|
||||
case left
|
||||
case right
|
||||
}
|
||||
|
||||
@objcMembers
|
||||
final class BubbleReactionsView: UIView, NibOwnerLoadable {
|
||||
|
@ -51,6 +58,12 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable {
|
|||
}
|
||||
}
|
||||
|
||||
var alignment: BubbleReactionsViewAlignment = .left {
|
||||
didSet {
|
||||
self.updateCollectionViewLayout(for: alignment)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
private func commonInit() {
|
||||
|
@ -87,7 +100,18 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable {
|
|||
self.collectionView.isScrollEnabled = false
|
||||
self.collectionView.delegate = self
|
||||
self.collectionView.dataSource = self
|
||||
self.collectionView.collectionViewLayout = DGCollectionViewLeftAlignFlowLayout()
|
||||
self.alignment = .left
|
||||
|
||||
self.collectionView.register(cellType: BubbleReactionViewCell.self)
|
||||
self.collectionView.register(cellType: BubbleReactionActionViewCell.self)
|
||||
self.collectionView.reloadData()
|
||||
}
|
||||
|
||||
private func updateCollectionViewLayout(for alignment: BubbleReactionsViewAlignment) {
|
||||
|
||||
let collectionViewLayout = self.collectionViewLayout(for: alignment)
|
||||
|
||||
self.collectionView.collectionViewLayout = collectionViewLayout
|
||||
|
||||
if let collectionViewFlowLayout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
|
||||
collectionViewFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
|
||||
|
@ -95,9 +119,22 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable {
|
|||
collectionViewFlowLayout.minimumLineSpacing = Constants.minimumLineSpacing
|
||||
}
|
||||
|
||||
self.collectionView.register(cellType: BubbleReactionViewCell.self)
|
||||
self.collectionView.register(cellType: BubbleReactionActionViewCell.self)
|
||||
self.collectionView.reloadData()
|
||||
self.collectionView.collectionViewLayout.invalidateLayout()
|
||||
}
|
||||
|
||||
private func collectionViewLayout(for alignment: BubbleReactionsViewAlignment) -> UICollectionViewLayout {
|
||||
|
||||
let collectionViewLayout: UICollectionViewLayout
|
||||
|
||||
switch alignment {
|
||||
case .left:
|
||||
collectionViewLayout = DGCollectionViewLeftAlignFlowLayout()
|
||||
case .right:
|
||||
collectionViewLayout = CollectionViewRightAlignFlowLayout()
|
||||
}
|
||||
|
||||
return collectionViewLayout
|
||||
}
|
||||
|
||||
private func setupLongPressGestureRecognizer() {
|
||||
|
|
|
@ -870,6 +870,12 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
|
|||
|
||||
- (BOOL)addEvent:(MXEvent*)event andRoomState:(MXRoomState*)roomState
|
||||
{
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
if (NO == [timelineConfiguration.currentStyle canAddEvent:event and:roomState to:self]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL shouldAddEvent = YES;
|
||||
|
||||
switch (self.tag)
|
||||
|
|
|
@ -372,6 +372,8 @@ const CGFloat kTypingCellHeight = 24;
|
|||
|
||||
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
|
||||
id<RoomTimelineCellDecorator> cellDecorator = [RoomTimelineConfiguration shared].currentStyle.cellDecorator;
|
||||
|
||||
// Finalize cell view customization here
|
||||
if ([cell isKindOfClass:MXKRoomBubbleTableViewCell.class])
|
||||
{
|
||||
|
@ -383,11 +385,8 @@ const CGFloat kTypingCellHeight = 24;
|
|||
|
||||
BOOL isCollapsableCellCollapsed = cellData.collapsable && cellData.collapsed;
|
||||
|
||||
// Display timestamp of the last message
|
||||
if (cellData.containsLastMessage && !isCollapsableCellCollapsed)
|
||||
{
|
||||
[bubbleCell addTimestampLabelForComponent:cellData.mostRecentComponentIndex];
|
||||
}
|
||||
// Display timestamp of the message if needed
|
||||
[cellDecorator addTimestampLabelIfNeededToCell:bubbleCell cellData:cellData];
|
||||
|
||||
NSMutableArray *temporaryViews = [NSMutableArray new];
|
||||
|
||||
|
@ -431,23 +430,8 @@ const CGFloat kTypingCellHeight = 24;
|
|||
urlPreviewView.tag = index;
|
||||
|
||||
[temporaryViews addObject:urlPreviewView];
|
||||
[bubbleCell.tmpSubviews addObject:urlPreviewView];
|
||||
|
||||
urlPreviewView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
urlPreviewView.availableWidth = cellData.maxTextViewWidth;
|
||||
[bubbleCell.contentView addSubview:urlPreviewView];
|
||||
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
if (roomBubbleCellData.containsBubbleComponentWithEncryptionBadge)
|
||||
{
|
||||
leftMargin+= RoomBubbleCellLayout.encryptedContentLeftMargin;
|
||||
}
|
||||
|
||||
// Set the preview view's origin
|
||||
[NSLayoutConstraint activateConstraints: @[
|
||||
[urlPreviewView.leadingAnchor constraintEqualToAnchor:urlPreviewView.superview.leadingAnchor constant:leftMargin],
|
||||
[urlPreviewView.topAnchor constraintEqualToAnchor:urlPreviewView.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.urlPreviewViewTopMargin + RoomBubbleCellLayout.reactionsViewTopMargin],
|
||||
]];
|
||||
[cellDecorator addURLPreviewView:urlPreviewView
|
||||
toCell:bubbleCell cellData:cellData contentViewPositionY:bottomPositionY];
|
||||
}
|
||||
|
||||
MXAggregatedReactions* reactions = cellData.reactions[componentEventId].aggregatedReactionsWithNonZeroCount;
|
||||
|
@ -469,44 +453,8 @@ const CGFloat kTypingCellHeight = 24;
|
|||
bubbleReactionsViewModel.viewModelDelegate = self;
|
||||
|
||||
[temporaryViews addObject:reactionsView];
|
||||
[bubbleCell.tmpSubviews addObject:reactionsView];
|
||||
|
||||
if ([[bubbleCell class] conformsToProtocol:@protocol(BubbleCellReactionsDisplayable)])
|
||||
{
|
||||
id<BubbleCellReactionsDisplayable> reactionsDisplayable = (id<BubbleCellReactionsDisplayable>)bubbleCell;
|
||||
[reactionsDisplayable addReactionsView:reactionsView];
|
||||
}
|
||||
else
|
||||
{
|
||||
reactionsView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[bubbleCell.contentView addSubview:reactionsView];
|
||||
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
|
||||
if (roomBubbleCellData.containsBubbleComponentWithEncryptionBadge)
|
||||
{
|
||||
leftMargin+= RoomBubbleCellLayout.encryptedContentLeftMargin;
|
||||
}
|
||||
|
||||
// The top constraint may need to include the URL preview view
|
||||
NSLayoutConstraint *topConstraint;
|
||||
if (urlPreviewView)
|
||||
{
|
||||
topConstraint = [reactionsView.topAnchor constraintEqualToAnchor:urlPreviewView.bottomAnchor constant:RoomBubbleCellLayout.reactionsViewTopMargin];
|
||||
}
|
||||
else
|
||||
{
|
||||
topConstraint = [reactionsView.topAnchor constraintEqualToAnchor:reactionsView.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.reactionsViewTopMargin];
|
||||
}
|
||||
|
||||
// Force receipts container size
|
||||
[NSLayoutConstraint activateConstraints:
|
||||
@[
|
||||
[reactionsView.leadingAnchor constraintEqualToAnchor:reactionsView.superview.leadingAnchor constant:leftMargin],
|
||||
[reactionsView.trailingAnchor constraintEqualToAnchor:reactionsView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin],
|
||||
topConstraint
|
||||
]];
|
||||
}
|
||||
[cellDecorator addReactionView:reactionsView toCell:bubbleCell
|
||||
cellData:cellData contentViewPositionY:bottomPositionY upperDecorationView:urlPreviewView];
|
||||
}
|
||||
|
||||
ThreadSummaryView *threadSummaryView;
|
||||
|
@ -518,43 +466,13 @@ const CGFloat kTypingCellHeight = 24;
|
|||
threadSummaryView.delegate = self;
|
||||
|
||||
[temporaryViews addObject:threadSummaryView];
|
||||
[bubbleCell.tmpSubviews addObject:threadSummaryView];
|
||||
UIView *upperDecorationView = reactionsView ?: urlPreviewView;
|
||||
|
||||
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)
|
||||
{
|
||||
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 constraintEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin]
|
||||
]];
|
||||
[cellDecorator addThreadSummaryView:threadSummaryView
|
||||
toCell:bubbleCell
|
||||
cellData:cellData
|
||||
contentViewPositionY:bottomPositionY
|
||||
upperDecorationView:upperDecorationView];
|
||||
}
|
||||
|
||||
MXKReceiptSendersContainer* avatarsContainer;
|
||||
|
@ -612,67 +530,13 @@ const CGFloat kTypingCellHeight = 24;
|
|||
avatarsContainer.accessibilityIdentifier = @"readReceiptsContainer";
|
||||
|
||||
[temporaryViews addObject:avatarsContainer];
|
||||
// Add this read receipts container in the content view
|
||||
[bubbleCell.tmpSubviews addObject:avatarsContainer];
|
||||
UIView *upperDecorationView = threadSummaryView ?: (reactionsView ?: urlPreviewView);
|
||||
|
||||
if ([[bubbleCell class] conformsToProtocol:@protocol(BubbleCellReadReceiptsDisplayable)])
|
||||
{
|
||||
id<BubbleCellReadReceiptsDisplayable> readReceiptsDisplayable = (id<BubbleCellReadReceiptsDisplayable>)bubbleCell;
|
||||
|
||||
[readReceiptsDisplayable addReadReceiptsView:avatarsContainer];
|
||||
}
|
||||
else
|
||||
{
|
||||
[bubbleCell.contentView addSubview:avatarsContainer];
|
||||
|
||||
// Force receipts container size
|
||||
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:RoomBubbleCellLayout.readReceiptsViewWidth];
|
||||
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:RoomBubbleCellLayout.readReceiptsViewHeight];
|
||||
|
||||
// Force receipts container position
|
||||
NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:avatarsContainer.superview
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
multiplier:1.0
|
||||
constant:-RoomBubbleCellLayout.readReceiptsViewRightMargin];
|
||||
|
||||
// At the bottom, we either have a thread summary, a reactions, a URL preview or nothing
|
||||
NSLayoutConstraint *topConstraint;
|
||||
if (threadSummaryView)
|
||||
{
|
||||
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:threadSummaryView.bottomAnchor constant:RoomBubbleCellLayout.readReceiptsViewTopMargin];
|
||||
}
|
||||
else if (reactionsView)
|
||||
{
|
||||
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:reactionsView.bottomAnchor constant:RoomBubbleCellLayout.readReceiptsViewTopMargin];
|
||||
}
|
||||
else if (urlPreviewView)
|
||||
{
|
||||
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:urlPreviewView.bottomAnchor constant:RoomBubbleCellLayout.readReceiptsViewTopMargin];
|
||||
}
|
||||
else
|
||||
{
|
||||
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:avatarsContainer.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.readReceiptsViewTopMargin];
|
||||
}
|
||||
|
||||
|
||||
// Available on iOS 8 and later
|
||||
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, topConstraint, trailingConstraint]];
|
||||
}
|
||||
[cellDecorator addReadReceiptsView:avatarsContainer
|
||||
toCell:bubbleCell
|
||||
cellData:cellData
|
||||
contentViewPositionY:bottomPositionY
|
||||
upperDecorationView:upperDecorationView];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -755,16 +619,7 @@ const CGFloat kTypingCellHeight = 24;
|
|||
// Check whether an event is currently selected: the other messages are then blurred
|
||||
if (_selectedEventId)
|
||||
{
|
||||
// Check whether the selected event belongs to this bubble
|
||||
NSInteger selectedComponentIndex = cellData.selectedComponentIndex;
|
||||
if (selectedComponentIndex != NSNotFound)
|
||||
{
|
||||
[bubbleCell selectComponent:cellData.selectedComponentIndex showEditButton:NO showTimestamp:cellData.showTimestampForSelectedComponent];
|
||||
}
|
||||
else
|
||||
{
|
||||
bubbleCell.blurred = YES;
|
||||
}
|
||||
[[RoomTimelineConfiguration shared].currentStyle applySelectedStyleIfNeededToCell:bubbleCell cellData:cellData];
|
||||
}
|
||||
|
||||
// Reset the marker if any
|
||||
|
@ -801,13 +656,24 @@ const CGFloat kTypingCellHeight = 24;
|
|||
// We are interested only by outgoing messages
|
||||
if ([cellData.senderId isEqualToString: self.mxSession.credentials.userId])
|
||||
{
|
||||
[bubbleCell updateTickViewWithFailedEventIds:self.failedEventIds];
|
||||
[cellDecorator addSendStatusViewToCell:bubbleCell
|
||||
withFailedEventIds:self.failedEventIds];
|
||||
}
|
||||
|
||||
// Make extra cell layout updates if needed
|
||||
[self updateCellLayoutIfNeeded:bubbleCell withCellData:cellData];
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)updateCellLayoutIfNeeded:(MXKRoomBubbleTableViewCell*)cell withCellData:(MXKRoomBubbleCellData*)cellData {
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
[timelineConfiguration.currentStyle.cellLayoutUpdater updateLayoutIfNeededFor:cell andCellData:cellData];
|
||||
}
|
||||
|
||||
- (RoomBubbleCellData*)roomBubbleCellDataForEventId:(NSString*)eventId
|
||||
{
|
||||
id<MXKRoomBubbleCellDataStoring> cellData = [self cellDataOfEventWithEventId:eventId];
|
||||
|
|
|
@ -18,7 +18,7 @@ import UIKit
|
|||
import Reusable
|
||||
import Mapbox
|
||||
|
||||
class LocationUserMarkerView: MGLAnnotationView, NibLoadable {
|
||||
class LocationMarkerView: MGLAnnotationView, NibLoadable {
|
||||
|
||||
@IBOutlet private var avatarView: UserAvatarView!
|
||||
|
76
Riot/Modules/Room/Location/LocationMarkerView.xib
Normal file
76
Riot/Modules/Room/Location/LocationMarkerView.xib
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="iN0-l3-epB" customClass="LocationMarkerView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="108"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GS1-Cw-Ezx">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="54"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="location_user_marker" translatesAutoresizingMaskIntoConstraints="NO" id="ldO-kc-R5W">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="54"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="41S-fj-tn4"/>
|
||||
<constraint firstAttribute="height" constant="54" id="MAX-5E-xvS"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="location_marker_icon" translatesAutoresizingMaskIntoConstraints="NO" id="gQe-Hv-22e">
|
||||
<rect key="frame" x="13" y="15" width="24" height="24"/>
|
||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="24" id="XuF-VU-qG2"/>
|
||||
<constraint firstAttribute="height" constant="24" id="ejE-pC-umv"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qut-wn-BX3" customClass="UserAvatarView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="2" y="2" width="46" height="46"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="46" id="BjG-I5-n8f"/>
|
||||
<constraint firstAttribute="width" constant="46" id="W3F-Aw-FO3"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="ldO-kc-R5W" firstAttribute="top" secondItem="GS1-Cw-Ezx" secondAttribute="top" id="1cb-YG-bcI"/>
|
||||
<constraint firstItem="ldO-kc-R5W" firstAttribute="leading" secondItem="GS1-Cw-Ezx" secondAttribute="leading" id="8I8-Zn-R5S"/>
|
||||
<constraint firstItem="gQe-Hv-22e" firstAttribute="centerY" secondItem="GS1-Cw-Ezx" secondAttribute="centerY" id="EE9-rM-y0V"/>
|
||||
<constraint firstItem="qut-wn-BX3" firstAttribute="centerY" secondItem="GS1-Cw-Ezx" secondAttribute="centerY" constant="-2" id="EQM-Hr-37h"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ldO-kc-R5W" secondAttribute="trailing" id="QUB-rY-t4j"/>
|
||||
<constraint firstItem="qut-wn-BX3" firstAttribute="centerX" secondItem="GS1-Cw-Ezx" secondAttribute="centerX" id="XLg-Qs-yTR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ldO-kc-R5W" secondAttribute="bottom" id="l4H-nN-44g"/>
|
||||
<constraint firstItem="gQe-Hv-22e" firstAttribute="centerX" secondItem="GS1-Cw-Ezx" secondAttribute="centerX" id="syG-Kp-4F9"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="GS1-Cw-Ezx" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="61F-Ve-exC"/>
|
||||
<constraint firstAttribute="trailing" secondItem="GS1-Cw-Ezx" secondAttribute="trailing" id="H8I-4T-A0M"/>
|
||||
<constraint firstItem="GS1-Cw-Ezx" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="hhI-gR-E5z"/>
|
||||
<constraint firstAttribute="bottom" secondItem="GS1-Cw-Ezx" secondAttribute="bottom" constant="54" id="mvD-6W-gMh"/>
|
||||
</constraints>
|
||||
<nil key="simulatedTopBarMetrics"/>
|
||||
<nil key="simulatedBottomBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<connections>
|
||||
<outlet property="avatarView" destination="qut-wn-BX3" id="wHA-bz-A2y"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="58.695652173913047" y="4.6875"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="location_marker_icon" width="24" height="24"/>
|
||||
<image name="location_user_marker" width="51" height="54.5"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -1,46 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="LocationUserMarkerView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="54"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="location_user_marker" translatesAutoresizingMaskIntoConstraints="NO" id="ldO-kc-R5W">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="54"/>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qut-wn-BX3" customClass="UserAvatarView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="2" y="2" width="46" height="46"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="ldO-kc-R5W" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="VF5-CP-8eH"/>
|
||||
<constraint firstItem="ldO-kc-R5W" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Voc-LH-fTw"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ldO-kc-R5W" secondAttribute="trailing" id="Vt0-UN-s20"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ldO-kc-R5W" secondAttribute="bottom" id="Ybf-8x-UaG"/>
|
||||
</constraints>
|
||||
<nil key="simulatedTopBarMetrics"/>
|
||||
<nil key="simulatedBottomBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<connections>
|
||||
<outlet property="avatarView" destination="qut-wn-BX3" id="wHA-bz-A2y"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-84.057971014492765" y="-80.357142857142847"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="location_user_marker" width="51" height="54.5"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -17,7 +17,6 @@
|
|||
import UIKit
|
||||
import Reusable
|
||||
import Mapbox
|
||||
import Keys
|
||||
|
||||
class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegate {
|
||||
|
||||
|
@ -25,7 +24,6 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
|||
|
||||
private struct Constants {
|
||||
static let mapHeight: CGFloat = 300.0
|
||||
static let mapTilerKey = RiotKeys().mapTilerAPIKey
|
||||
static let mapZoomLevel = 15.0
|
||||
static let cellBorderRadius: CGFloat = 1.0
|
||||
static let cellCornerRadius: CGFloat = 8.0
|
||||
|
@ -36,9 +34,10 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
|||
|
||||
@IBOutlet private var descriptionContainerView: UIView!
|
||||
@IBOutlet private var descriptionLabel: UILabel!
|
||||
@IBOutlet private var descriptionIcon: UIImageView!
|
||||
|
||||
private var mapView: MGLMapView!
|
||||
private var annotationView: LocationUserMarkerView?
|
||||
private var annotationView: LocationMarkerView?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
|
@ -73,19 +72,13 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
|||
|
||||
// MARK: - Public
|
||||
|
||||
public func displayLocation(_ location: CLLocationCoordinate2D,
|
||||
userIdentifier: String,
|
||||
userDisplayName: String,
|
||||
userAvatarURLString: String?,
|
||||
mediaManager: MXMediaManager) {
|
||||
public func displayLocation(_ location: CLLocationCoordinate2D, userAvatarData: AvatarViewData? = nil) {
|
||||
|
||||
annotationView = LocationUserMarkerView.loadFromNib()
|
||||
annotationView = LocationMarkerView.loadFromNib()
|
||||
|
||||
annotationView?.setAvatarData(AvatarViewData(matrixItemId: userIdentifier,
|
||||
displayName: userDisplayName,
|
||||
avatarUrl: userAvatarURLString,
|
||||
mediaManager: mediaManager,
|
||||
fallbackImage: .matrixItem(userIdentifier, userDisplayName)))
|
||||
if let userAvatarData = userAvatarData {
|
||||
annotationView?.setAvatarData(userAvatarData)
|
||||
}
|
||||
|
||||
if let annotations = mapView.annotations {
|
||||
mapView.removeAnnotations(annotations)
|
||||
|
@ -103,6 +96,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
|||
func update(theme: Theme) {
|
||||
descriptionLabel.textColor = theme.colors.primaryContent
|
||||
descriptionLabel.font = theme.fonts.footnote
|
||||
descriptionIcon.tintColor = theme.colors.accent
|
||||
layer.borderColor = theme.colors.quinaryContent.cgColor
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<connections>
|
||||
<outlet property="descriptionContainerView" destination="oVd-gS-Rmb" id="Npu-jp-oYo"/>
|
||||
<outlet property="descriptionIcon" destination="GP2-dA-giJ" id="7YL-UU-ClT"/>
|
||||
<outlet property="descriptionLabel" destination="c68-l7-McA" id="HiH-8Q-yTp"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="165.94202898550725" y="-100.78125"/>
|
||||
|
|
|
@ -36,16 +36,6 @@
|
|||
|
||||
#import "MXKRoomBubbleCellData.h"
|
||||
|
||||
#import "MXKRoomIncomingTextMsgBubbleCell.h"
|
||||
#import "MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "MXKRoomIncomingAttachmentBubbleCell.h"
|
||||
#import "MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
|
||||
#import "MXKRoomOutgoingTextMsgBubbleCell.h"
|
||||
#import "MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "MXKRoomOutgoingAttachmentBubbleCell.h"
|
||||
#import "MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
|
||||
#import "MXKEncryptionKeysImportView.h"
|
||||
|
||||
#import "NSBundle+MatrixKit.h"
|
||||
|
@ -616,17 +606,6 @@
|
|||
_bubblesTableView.delegate = self;
|
||||
_bubblesTableView.dataSource = roomDataSource; // Note: data source may be nil here, it will be set during [displayRoom:] call.
|
||||
|
||||
// Set up default classes to use for cells
|
||||
[_bubblesTableView registerClass:MXKRoomIncomingTextMsgBubbleCell.class forCellReuseIdentifier:MXKRoomIncomingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[_bubblesTableView registerClass:MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[_bubblesTableView registerClass:MXKRoomIncomingAttachmentBubbleCell.class forCellReuseIdentifier:MXKRoomIncomingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[_bubblesTableView registerClass:MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[_bubblesTableView registerClass:MXKRoomOutgoingTextMsgBubbleCell.class forCellReuseIdentifier:MXKRoomOutgoingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[_bubblesTableView registerClass:MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[_bubblesTableView registerClass:MXKRoomOutgoingAttachmentBubbleCell.class forCellReuseIdentifier:MXKRoomOutgoingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[_bubblesTableView registerClass:MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Observe kMXSessionWillLeaveRoomNotification to be notified if the user leaves the current room.
|
||||
MXWeakify(self);
|
||||
_mxSessionWillLeaveRoomNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionWillLeaveRoomNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
@ -2477,64 +2456,7 @@
|
|||
|
||||
- (Class<MXKCellRendering>)cellViewClassForCellData:(MXKCellData*)cellData
|
||||
{
|
||||
Class cellViewClass = nil;
|
||||
|
||||
// Sanity check
|
||||
if ([cellData conformsToProtocol:@protocol(MXKRoomBubbleCellDataStoring)])
|
||||
{
|
||||
id<MXKRoomBubbleCellDataStoring> bubbleData = (id<MXKRoomBubbleCellDataStoring>)cellData;
|
||||
|
||||
// Select the suitable table view cell class
|
||||
if (bubbleData.isIncoming)
|
||||
{
|
||||
if (bubbleData.isAttachmentWithThumbnail)
|
||||
{
|
||||
if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.class;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = MXKRoomIncomingAttachmentBubbleCell.class;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.class;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = MXKRoomIncomingTextMsgBubbleCell.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bubbleData.isAttachmentWithThumbnail)
|
||||
{
|
||||
if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = MXKRoomOutgoingAttachmentBubbleCell.class;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = MXKRoomOutgoingTextMsgBubbleCell.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cellViewClass;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)cellReuseIdentifierForCellData:(MXKCellData*)cellData
|
|
@ -54,55 +54,7 @@
|
|||
#import "JitsiViewController.h"
|
||||
|
||||
#import "RoomEmptyBubbleCell.h"
|
||||
|
||||
#import "RoomIncomingTextMsgBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomIncomingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomOutgoingTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomOutgoingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomMembershipBubbleCell.h"
|
||||
#import "RoomMembershipWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomMembershipCollapsedBubbleCell.h"
|
||||
#import "RoomMembershipCollapsedWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomMembershipExpandedBubbleCell.h"
|
||||
#import "RoomMembershipExpandedWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomCreationWithPaginationCollapsedBubbleCell.h"
|
||||
#import "RoomCreationCollapsedBubbleCell.h"
|
||||
|
||||
#import "RoomSelectedStickerBubbleCell.h"
|
||||
#import "RoomPredecessorBubbleCell.h"
|
||||
|
||||
#import "MXKRoomBubbleTableViewCell+Riot.h"
|
||||
|
||||
#import "AvatarGenerator.h"
|
||||
|
@ -130,6 +82,8 @@
|
|||
|
||||
#import "MXSDKOptions.h"
|
||||
|
||||
#import "RoomTimelineCellProvider.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNotification";
|
||||
|
@ -367,83 +321,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
[super viewDidLoad];
|
||||
|
||||
// Register first customized cell view classes used to render bubbles
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomOutgoingAttachmentBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedAttachmentBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomEmptyBubbleCell.class forCellReuseIdentifier:RoomEmptyBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomMembershipBubbleCell.class forCellReuseIdentifier:RoomMembershipBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipCollapsedBubbleCell.class forCellReuseIdentifier:RoomMembershipCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipCollapsedWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipCollapsedWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipExpandedBubbleCell.class forCellReuseIdentifier:RoomMembershipExpandedBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipExpandedWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipExpandedWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomSelectedStickerBubbleCell.class forCellReuseIdentifier:RoomSelectedStickerBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomPredecessorBubbleCell.class forCellReuseIdentifier:RoomPredecessorBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:KeyVerificationIncomingRequestApprovalBubbleCell.class forCellReuseIdentifier:KeyVerificationIncomingRequestApprovalBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationRequestStatusBubbleCell.class forCellReuseIdentifier:KeyVerificationRequestStatusBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationRequestStatusWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationRequestStatusWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationConclusionBubbleCell.class forCellReuseIdentifier:KeyVerificationConclusionBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationConclusionWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationConclusionWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomCreationCollapsedBubbleCell.class forCellReuseIdentifier:RoomCreationCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomCreationWithPaginationCollapsedBubbleCell.class forCellReuseIdentifier:RoomCreationWithPaginationCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// call cells
|
||||
[self.bubblesTableView registerClass:RoomDirectCallStatusBubbleCell.class forCellReuseIdentifier:RoomDirectCallStatusBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomGroupCallStatusBubbleCell.class forCellReuseIdentifier:RoomGroupCallStatusBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomCreationIntroCell.class forCellReuseIdentifier:RoomCreationIntroCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerNib:RoomTypingBubbleCell.nib forCellReuseIdentifier:RoomTypingBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:VoiceMessageBubbleCell.class forCellReuseIdentifier:VoiceMessageBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:VoiceMessageWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:VoiceMessageWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:VoiceMessageWithPaginationTitleBubbleCell.class forCellReuseIdentifier:VoiceMessageWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:PollBubbleCell.class forCellReuseIdentifier:PollBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:PollWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:PollWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:PollWithPaginationTitleBubbleCell.class forCellReuseIdentifier:PollWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:LocationBubbleCell.class forCellReuseIdentifier:LocationBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:LocationWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:LocationWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:LocationWithPaginationTitleBubbleCell.class forCellReuseIdentifier:LocationWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[[RoomTimelineConfiguration shared].currentStyle.cellProvider registerCellsForTableView:self.bubblesTableView];
|
||||
|
||||
[self vc_removeBackTitle];
|
||||
|
||||
|
@ -2236,6 +2114,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
[MXSDKOptions sharedInstance].videoConversionPresetName = presetName;
|
||||
[roomInputToolbarView sendSelectedVideoAsset:videoAsset isPhotoLibraryAsset:isPhotoLibraryAsset];
|
||||
}];
|
||||
compressionPrompt.popoverPresentationController.sourceView = roomInputToolbarView.attachMediaButton;
|
||||
compressionPrompt.popoverPresentationController.sourceRect = roomInputToolbarView.attachMediaButton.bounds;
|
||||
|
||||
[self presentViewController:compressionPrompt animated:YES completion:nil];
|
||||
}
|
||||
|
@ -2698,15 +2578,24 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
|
||||
- (Class<MXKCellRendering>)cellViewClassForCellData:(MXKCellData*)cellData
|
||||
{
|
||||
Class cellViewClass = nil;
|
||||
BOOL showEncryptionBadge = NO;
|
||||
RoomTimelineCellIdentifier cellIdentifier = [self cellIdentifierForCellData:cellData andRoomDataSource:customizedRoomDataSource];
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
return [timelineConfiguration.currentStyle.cellProvider cellViewClassForCellIdentifier:cellIdentifier];;
|
||||
}
|
||||
|
||||
- (RoomTimelineCellIdentifier)cellIdentifierForCellData:(MXKCellData*)cellData andRoomDataSource:(RoomDataSource *)customizedRoomDataSource;
|
||||
{
|
||||
// Sanity check
|
||||
if (![cellData conformsToProtocol:@protocol(MXKRoomBubbleCellDataStoring)])
|
||||
{
|
||||
return nil;
|
||||
return RoomTimelineCellIdentifierUnknown;
|
||||
}
|
||||
|
||||
BOOL showEncryptionBadge = NO;
|
||||
RoomTimelineCellIdentifier cellIdentifier;
|
||||
|
||||
id<MXKRoomBubbleCellDataStoring> bubbleData = (id<MXKRoomBubbleCellDataStoring>)cellData;
|
||||
|
||||
MXKRoomBubbleCellData *roomBubbleCellData;
|
||||
|
@ -2720,27 +2609,27 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
// Select the suitable table view cell class, by considering first the empty bubble cell.
|
||||
if (bubbleData.hasNoDisplay)
|
||||
{
|
||||
cellViewClass = RoomEmptyBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierEmpty;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagRoomCreationIntro)
|
||||
{
|
||||
cellViewClass = RoomCreationIntroCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierRoomCreationIntro;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagRoomCreateWithPredecessor)
|
||||
{
|
||||
cellViewClass = RoomPredecessorBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierRoomPredecessor;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagKeyVerificationRequestIncomingApproval)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.class : KeyVerificationIncomingRequestApprovalBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierKeyVerificationIncomingRequestApprovalWithPaginationTitle : RoomTimelineCellIdentifierKeyVerificationIncomingRequestApproval;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagKeyVerificationRequest)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? KeyVerificationRequestStatusWithPaginationTitleBubbleCell.class : KeyVerificationRequestStatusBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierKeyVerificationRequestStatusWithPaginationTitle : RoomTimelineCellIdentifierKeyVerificationRequestStatus;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagKeyVerificationConclusion)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? KeyVerificationConclusionWithPaginationTitleBubbleCell.class : KeyVerificationConclusionBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierKeyVerificationConclusionWithPaginationTitle : RoomTimelineCellIdentifierKeyVerificationConclusion;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagMembership)
|
||||
{
|
||||
|
@ -2748,80 +2637,80 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
{
|
||||
if (bubbleData.nextCollapsableCellData)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomMembershipCollapsedWithPaginationTitleBubbleCell.class : RoomMembershipCollapsedBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierMembershipCollapsedWithPaginationTitle : RoomTimelineCellIdentifierMembershipCollapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use a normal membership cell for a single membership event
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomMembershipWithPaginationTitleBubbleCell.class : RoomMembershipBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierMembershipWithPaginationTitle : RoomTimelineCellIdentifierMembership;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.collapsedAttributedTextMessage)
|
||||
{
|
||||
// The cell (and its series) is not collapsed but this cell is the first
|
||||
// of the series. So, use the cell with the "collapse" button.
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomMembershipExpandedWithPaginationTitleBubbleCell.class : RoomMembershipExpandedBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierMembershipExpandedWithPaginationTitle : RoomTimelineCellIdentifierMembershipExpanded;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomMembershipWithPaginationTitleBubbleCell.class : RoomMembershipBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierMembershipWithPaginationTitle : RoomTimelineCellIdentifierMembership;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagRoomCreateConfiguration)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomCreationWithPaginationCollapsedBubbleCell.class : RoomCreationCollapsedBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierRoomCreationCollapsedWithPaginationTitle : RoomTimelineCellIdentifierRoomCreationCollapsed;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagCall)
|
||||
{
|
||||
cellViewClass = RoomDirectCallStatusBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierDirectCallStatus;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagGroupCall)
|
||||
{
|
||||
cellViewClass = RoomGroupCallStatusBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierGroupCallStatus;
|
||||
}
|
||||
else if (bubbleData.attachment.type == MXKAttachmentTypeVoiceMessage || bubbleData.attachment.type == MXKAttachmentTypeAudio)
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = VoiceMessageWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierVoiceMessageWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = VoiceMessageWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierVoiceMessageWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = VoiceMessageBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierVoiceMessage;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagPoll)
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = PollWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierPollWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = PollWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierPollWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = PollBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierPoll;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagLocation)
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = LocationWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierLocationWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = LocationWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierLocationWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = LocationBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierLocation;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.isIncoming)
|
||||
|
@ -2831,19 +2720,19 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
// Check whether the provided celldata corresponds to a selected sticker
|
||||
if (customizedRoomDataSource.selectedEventId && (bubbleData.attachment.type == MXKAttachmentTypeSticker) && [bubbleData.attachment.eventId isEqualToString:customizedRoomDataSource.selectedEventId])
|
||||
{
|
||||
cellViewClass = RoomSelectedStickerBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierSelectedSticker;
|
||||
}
|
||||
else if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class : RoomIncomingAttachmentWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithPaginationTitle : RoomTimelineCellIdentifierIncomingAttachmentWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class : RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithoutSenderInfo : RoomTimelineCellIdentifierIncomingAttachmentWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedAttachmentBubbleCell.class : RoomIncomingAttachmentBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingAttachmentEncrypted : RoomTimelineCellIdentifierIncomingAttachment;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2852,24 +2741,24 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
{
|
||||
if (bubbleData.shouldHideSenderName)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class : RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitleWithoutSenderName : RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitleWithoutSenderName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.class : RoomIncomingTextMsgWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitle : RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitle;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.class : RoomIncomingTextMsgWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderInfo : RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderInfo;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderName)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.class : RoomIncomingTextMsgWithoutSenderNameBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderName : RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgBubbleCell.class : RoomIncomingTextMsgBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncrypted : RoomTimelineCellIdentifierIncomingTextMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2881,19 +2770,19 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
// Check whether the provided celldata corresponds to a selected sticker
|
||||
if (customizedRoomDataSource.selectedEventId && (bubbleData.attachment.type == MXKAttachmentTypeSticker) && [bubbleData.attachment.eventId isEqualToString:customizedRoomDataSource.selectedEventId])
|
||||
{
|
||||
cellViewClass = RoomSelectedStickerBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierSelectedSticker;
|
||||
}
|
||||
else if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class :RoomOutgoingAttachmentWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithPaginationTitle : RoomTimelineCellIdentifierOutgoingAttachmentWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class : RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithoutSenderInfo : RoomTimelineCellIdentifierOutgoingAttachmentWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedAttachmentBubbleCell.class : RoomOutgoingAttachmentBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingAttachmentEncrypted : RoomTimelineCellIdentifierOutgoingAttachment;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2902,29 +2791,29 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
|||
{
|
||||
if (bubbleData.shouldHideSenderName)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class : RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitleWithoutSenderName : RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitleWithoutSenderName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.class : RoomOutgoingTextMsgWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitle : RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitle;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class :RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderInfo : RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderInfo;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderName)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class : RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderName : RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgBubbleCell.class : RoomOutgoingTextMsgBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncrypted : RoomTimelineCellIdentifierOutgoingTextMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cellViewClass;
|
||||
return cellIdentifier;
|
||||
}
|
||||
|
||||
#pragma mark - MXKDataSource delegate
|
||||
|
|
|
@ -216,6 +216,7 @@ extern NSString *const kMXKRoomBubbleCellUrlItemInteraction;
|
|||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewMinHeightConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewBottomConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewLeadingConstraint;
|
||||
|
||||
/**
|
||||
The constraints which defines the relationship between bubbleInfoContainer and its superview
|
||||
|
@ -325,4 +326,7 @@ extern NSString *const kMXKRoomBubbleCellUrlItemInteraction;
|
|||
*/
|
||||
- (void)setupViews;
|
||||
|
||||
/// Add temporary subview to `tmpSubviews` property.
|
||||
- (void)addTemporarySubview:(UIView*)subview;
|
||||
|
||||
@end
|
|
@ -1128,6 +1128,16 @@ static BOOL _disableLongPressGestureOnEvent;
|
|||
[self resetAttachmentViewBottomConstraintConstant];
|
||||
}
|
||||
|
||||
- (void)addTemporarySubview:(UIView*)subview
|
||||
{
|
||||
if (!self.tmpSubviews)
|
||||
{
|
||||
self.tmpSubviews = [NSMutableArray new];
|
||||
}
|
||||
|
||||
[self.tmpSubviews addObject:subview];
|
||||
}
|
||||
|
||||
#pragma mark - Attachment progress handling
|
||||
|
||||
- (void)updateProgressUI:(NSDictionary*)statisticsDict
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -128,6 +128,7 @@
|
|||
<connections>
|
||||
<outlet property="activityIndicator" destination="OrM-nA-kyg" id="Frc-ED-PlH"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewLeadingConstraint" destination="p93-5h-lvW" id="WRx-S5-r3M"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="C5F-6D-LZx" id="frk-Ox-WbA"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -161,6 +161,7 @@
|
|||
<connections>
|
||||
<outlet property="activityIndicator" destination="jmK-pe-WZd" id="F7y-hE-pcg"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewLeadingConstraint" destination="6mM-Ag-m0K" id="lG4-bl-Kio"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="C5F-6D-LZx" id="frk-Ox-WbA"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2015 OpenMarket 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 "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
/**
|
||||
`RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell` displays outgoing attachment bubbles and pagination title but no sender name.
|
||||
*/
|
||||
@interface RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell : RoomOutgoingAttachmentWithPaginationTitleBubbleCell
|
||||
|
||||
@end
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations 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 "RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
|
||||
#import "ThemeService.h"
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell
|
||||
|
||||
- (void)customizeTableViewCellRendering
|
||||
{
|
||||
[super customizeTableViewCellRendering];
|
||||
|
||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,161 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="WmY-Jw-mqv" customClass="RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SFg-55-RF4" userLabel="Pagination Title View">
|
||||
<rect key="frame" x="56" y="10" width="534" height="24"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wkY-7Y-sGw" userLabel="Pagination Label">
|
||||
<rect key="frame" x="0.0" y="0.0" width="524" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="18" id="PiZ-Ag-oxc"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<color key="textColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0kR-4b-Wav" userLabel="Pagination Separator View">
|
||||
<rect key="frame" x="0.0" y="23" width="534" height="1"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="PaginationTitleView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="wkY-7Y-sGw" secondAttribute="trailing" constant="10" id="4DU-xA-diS"/>
|
||||
<constraint firstItem="wkY-7Y-sGw" firstAttribute="top" secondItem="SFg-55-RF4" secondAttribute="top" id="6Cz-bj-kUg"/>
|
||||
<constraint firstItem="0kR-4b-Wav" firstAttribute="top" secondItem="wkY-7Y-sGw" secondAttribute="bottom" constant="5" id="K4B-zf-5x2"/>
|
||||
<constraint firstAttribute="height" constant="24" id="Qo9-cw-LCa"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0kR-4b-Wav" secondAttribute="trailing" id="fnd-bR-QmB"/>
|
||||
<constraint firstAttribute="bottom" secondItem="0kR-4b-Wav" secondAttribute="bottom" id="pBK-pC-oCA"/>
|
||||
<constraint firstItem="0kR-4b-Wav" firstAttribute="leading" secondItem="SFg-55-RF4" secondAttribute="leading" id="rhH-Hz-w9J"/>
|
||||
<constraint firstItem="wkY-7Y-sGw" firstAttribute="leading" secondItem="SFg-55-RF4" secondAttribute="leading" id="uq9-MP-Dmm"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="hgp-Z5-rAj" userLabel="Picture View" customClass="MXKImageView">
|
||||
<rect key="frame" x="13" y="54" width="30" height="30"/>
|
||||
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="PictureView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="30" id="NQk-ck-Lo8"/>
|
||||
<constraint firstAttribute="height" constant="30" id="dNT-QU-CUG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
|
||||
<rect key="frame" x="56" y="45" width="192" height="65"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="AttachmentView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="192" id="9zO-jU-qTb"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="34" id="C5F-6D-LZx"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="K9X-gn-noF" userLabel="File Type Image View">
|
||||
<rect key="frame" x="56" y="45" width="32" height="32"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="FileTypeImageView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="OE8-oh-B7Q"/>
|
||||
<constraint firstAttribute="height" constant="32" id="jJB-zj-fbT"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Cot-3X-2cU" userLabel="Play Icon Image View">
|
||||
<rect key="frame" x="136" y="61.5" width="32" height="32"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="PlayIconImageView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="8io-Wk-GzF"/>
|
||||
<constraint firstAttribute="width" constant="32" id="aeJ-j3-rfX"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="jmK-pe-WZd">
|
||||
<rect key="frame" x="142" y="67.5" width="20" height="20"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="ActivityIndicator"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</activityIndicatorView>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW">
|
||||
<rect key="frame" x="515" y="54" width="70" height="66"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="70" id="tLr-6k-ArA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
|
||||
<rect key="frame" x="487" y="50" width="100" height="70"/>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/>
|
||||
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3b7-4a-YL0">
|
||||
<rect key="frame" x="8" y="3" width="584" height="114"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="3b7-4a-YL0" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="topMargin" constant="-8" id="10i-70-PDz"/>
|
||||
<constraint firstItem="hgp-Z5-rAj" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="54" id="2Ih-ga-N9s"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="13" id="6mM-Ag-m0K"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="45" id="96U-67-5TP"/>
|
||||
<constraint firstAttribute="bottom" secondItem="fdx-qs-8en" secondAttribute="bottom" id="AeT-4F-mKp"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/>
|
||||
<constraint firstItem="SFg-55-RF4" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="56" id="I4N-5Q-LFe"/>
|
||||
<constraint firstItem="jmK-pe-WZd" firstAttribute="centerX" secondItem="5IE-JS-uf3" secondAttribute="centerX" id="IoK-NR-EyQ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" constant="10" id="SHN-tC-zsJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/>
|
||||
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="54" id="XSL-TG-m62"/>
|
||||
<constraint firstItem="3b7-4a-YL0" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leadingMargin" constant="-8" id="aGh-ad-trR"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="3b7-4a-YL0" secondAttribute="trailing" constant="-8" id="abE-n9-N8T"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="15" id="hQV-lO-7aQ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="SFg-55-RF4" secondAttribute="trailing" constant="10" id="jvR-oT-EQF"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="K9X-gn-noF" secondAttribute="leading" id="p93-5h-lvW"/>
|
||||
<constraint firstItem="jmK-pe-WZd" firstAttribute="centerY" secondItem="5IE-JS-uf3" secondAttribute="centerY" id="qqJ-jh-rGK"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/>
|
||||
<constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="13" id="tuw-aU-ncu"/>
|
||||
<constraint firstItem="SFg-55-RF4" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="wJX-7V-bJB"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="3b7-4a-YL0" secondAttribute="bottom" constant="-8" id="wpa-8Z-Gy3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="RoomBubbleCell"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="jmK-pe-WZd" id="F7y-hE-pcg"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewLeadingConstraint" destination="6mM-Ag-m0K" id="lG4-bl-Kio"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="C5F-6D-LZx" id="frk-Ox-WbA"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
<outlet property="attachmentView" destination="5IE-JS-uf3" id="imT-1z-hR1"/>
|
||||
<outlet property="bubbleInfoContainer" destination="IOg-Kt-8vW" id="TAw-QY-Y9e"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="XSL-TG-m62" id="qVf-vJ-4aP"/>
|
||||
<outlet property="bubbleOverlayContainer" destination="3b7-4a-YL0" id="KNb-h4-YHD"/>
|
||||
<outlet property="fileTypeIconView" destination="K9X-gn-noF" id="4Pj-bc-3gk"/>
|
||||
<outlet property="paginationLabel" destination="wkY-7Y-sGw" id="9Uh-tX-t0I"/>
|
||||
<outlet property="paginationSeparatorView" destination="0kR-4b-Wav" id="c7x-Sh-aj6"/>
|
||||
<outlet property="paginationTitleView" destination="SFg-55-RF4" id="mbP-6I-gOn"/>
|
||||
<outlet property="pictureView" destination="hgp-Z5-rAj" id="rKM-QG-RJN"/>
|
||||
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
|
||||
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-26" y="113"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -95,6 +95,7 @@
|
|||
<connections>
|
||||
<outlet property="activityIndicator" destination="8Bq-Mk-bN8" id="cbT-lK-yjP"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewLeadingConstraint" destination="bSL-lG-ued" id="M5E-Ot-73d"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="Uqr-7d-0dv" id="UIs-4K-np5"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#import "MXKImageView.h"
|
||||
#import "MXKPieChartView.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation MXKRoomOutgoingAttachmentBubbleCell
|
||||
|
||||
- (void)dealloc
|
||||
|
@ -30,6 +32,15 @@
|
|||
[self stopAnimating];
|
||||
}
|
||||
|
||||
- (void)setupViews
|
||||
{
|
||||
[super setupViews];
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
[timelineConfiguration.currentStyle.cellLayoutUpdater setupLayoutForOutgoingFileAttachmentCell:self];
|
||||
}
|
||||
|
||||
- (void)render:(MXKCellData *)cellData
|
||||
{
|
||||
[super render:cellData];
|
|
@ -37,11 +37,17 @@ class LocationBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable
|
|||
|
||||
let location = CLLocationCoordinate2D(latitude: locationContent.latitude, longitude: locationContent.longitude)
|
||||
|
||||
locationView.displayLocation(location,
|
||||
userIdentifier: bubbleData.senderId,
|
||||
userDisplayName: bubbleData.senderDisplayName,
|
||||
userAvatarURLString: bubbleData.senderAvatarUrl,
|
||||
mediaManager: bubbleData.mxSession.mediaManager)
|
||||
if locationContent.assetType == .user {
|
||||
let avatarViewData = AvatarViewData(matrixItemId: bubbleData.senderId,
|
||||
displayName: bubbleData.senderDisplayName,
|
||||
avatarUrl: bubbleData.senderAvatarUrl,
|
||||
mediaManager: bubbleData.mxSession.mediaManager,
|
||||
fallbackImage: .matrixItem(bubbleData.senderId, bubbleData.senderDisplayName))
|
||||
|
||||
locationView.displayLocation(location, userAvatarData: avatarViewData)
|
||||
} else {
|
||||
locationView.displayLocation(location)
|
||||
}
|
||||
}
|
||||
|
||||
override func setupViews() {
|
||||
|
|
115
Riot/Modules/Room/Views/BubbleCells/RoomTimelineCellIdentifier.h
Normal file
115
Riot/Modules/Room/Views/BubbleCells/RoomTimelineCellIdentifier.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
/// RoomTimelineCellIdentifier represents room timeline cell identifiers.
|
||||
typedef NS_ENUM(NSUInteger, RoomTimelineCellIdentifier) {
|
||||
|
||||
RoomTimelineCellIdentifierUnknown,
|
||||
|
||||
// - Text message
|
||||
// -- Incoming
|
||||
// --- Clear
|
||||
RoomTimelineCellIdentifierIncomingTextMessage,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderName,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitleWithoutSenderName,
|
||||
// --- Encrypted
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncrypted,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderName,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitleWithoutSenderName,
|
||||
// -- Outgoing
|
||||
// --- Clear
|
||||
RoomTimelineCellIdentifierOutgoingTextMessage,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderName,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitleWithoutSenderName,
|
||||
// --- Encrypted
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncrypted,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderName,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitleWithoutSenderName,
|
||||
|
||||
// - Attachment
|
||||
// -- Incoming
|
||||
// --- Clear
|
||||
RoomTimelineCellIdentifierIncomingAttachment,
|
||||
RoomTimelineCellIdentifierIncomingAttachmentWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierIncomingAttachmentWithPaginationTitle,
|
||||
// --- Encrypted
|
||||
RoomTimelineCellIdentifierIncomingAttachmentEncrypted,
|
||||
RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithPaginationTitle,
|
||||
// -- Outgoing
|
||||
// --- Clear
|
||||
RoomTimelineCellIdentifierOutgoingAttachment,
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentWithPaginationTitle,
|
||||
// --- Encrypted
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentEncrypted,
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithPaginationTitle,
|
||||
|
||||
// - Room membership
|
||||
RoomTimelineCellIdentifierMembership,
|
||||
RoomTimelineCellIdentifierMembershipWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierMembershipCollapsed,
|
||||
RoomTimelineCellIdentifierMembershipCollapsedWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierMembershipExpanded,
|
||||
RoomTimelineCellIdentifierMembershipExpandedWithPaginationTitle,
|
||||
|
||||
// - Key verification
|
||||
RoomTimelineCellIdentifierKeyVerificationIncomingRequestApproval,
|
||||
RoomTimelineCellIdentifierKeyVerificationIncomingRequestApprovalWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierKeyVerificationRequestStatus,
|
||||
RoomTimelineCellIdentifierKeyVerificationRequestStatusWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierKeyVerificationConclusion,
|
||||
RoomTimelineCellIdentifierKeyVerificationConclusionWithPaginationTitle,
|
||||
|
||||
// - Room creation
|
||||
RoomTimelineCellIdentifierRoomCreationCollapsed,
|
||||
RoomTimelineCellIdentifierRoomCreationCollapsedWithPaginationTitle,
|
||||
|
||||
// - Call
|
||||
RoomTimelineCellIdentifierDirectCallStatus,
|
||||
RoomTimelineCellIdentifierGroupCallStatus,
|
||||
|
||||
// - Voice message
|
||||
RoomTimelineCellIdentifierVoiceMessage,
|
||||
RoomTimelineCellIdentifierVoiceMessageWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierVoiceMessageWithPaginationTitle,
|
||||
|
||||
// - Poll
|
||||
RoomTimelineCellIdentifierPoll,
|
||||
RoomTimelineCellIdentifierPollWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierPollWithPaginationTitle,
|
||||
|
||||
// - Location sharing
|
||||
RoomTimelineCellIdentifierLocation,
|
||||
RoomTimelineCellIdentifierLocationWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierLocationWithPaginationTitle,
|
||||
|
||||
// - Others
|
||||
RoomTimelineCellIdentifierEmpty,
|
||||
RoomTimelineCellIdentifierSelectedSticker,
|
||||
RoomTimelineCellIdentifierRoomPredecessor,
|
||||
RoomTimelineCellIdentifierRoomCreationIntro,
|
||||
RoomTimelineCellIdentifierTyping
|
||||
};
|
|
@ -0,0 +1,96 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
/// RoomTimelineConfiguration enables to manage room timeline appearance configuration
|
||||
@objcMembers
|
||||
class RoomTimelineConfiguration: NSObject {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
static let shared = RoomTimelineConfiguration()
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private(set) var currentStyle: RoomTimelineStyle
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(style: RoomTimelineStyle) {
|
||||
self.currentStyle = style
|
||||
|
||||
super.init()
|
||||
|
||||
self.registerThemeDidChange()
|
||||
}
|
||||
|
||||
convenience init(styleIdentifier: RoomTimelineStyleIdentifier) {
|
||||
|
||||
let style = type(of: self).style(for: styleIdentifier)
|
||||
self.init(style: style)
|
||||
}
|
||||
|
||||
convenience override init() {
|
||||
let styleIdentifier = RiotSettings.shared.roomTimelineStyleIdentifier
|
||||
self.init(styleIdentifier: styleIdentifier)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func updateStyle(_ roomTimelineStyle: RoomTimelineStyle) {
|
||||
self.currentStyle = roomTimelineStyle
|
||||
}
|
||||
|
||||
func updateStyle(withIdentifier identifier: RoomTimelineStyleIdentifier) {
|
||||
|
||||
let style = type(of: self).style(for: identifier)
|
||||
|
||||
self.updateStyle(style)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func registerThemeDidChange() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange(notification:)), name: .themeServiceDidChangeTheme, object: nil)
|
||||
|
||||
}
|
||||
|
||||
@objc private func themeDidChange(notification: Notification) {
|
||||
|
||||
guard let themeService = notification.object as? ThemeService else {
|
||||
return
|
||||
}
|
||||
|
||||
self.currentStyle.update(theme: themeService.theme)
|
||||
}
|
||||
|
||||
private class func style(for identifier: RoomTimelineStyleIdentifier) -> RoomTimelineStyle {
|
||||
|
||||
let roomTimelineStyle: RoomTimelineStyle
|
||||
|
||||
let theme = ThemeService.shared().theme
|
||||
|
||||
switch identifier {
|
||||
case .plain:
|
||||
roomTimelineStyle = PlainRoomTimelineStyle(theme: theme)
|
||||
case .bubble:
|
||||
roomTimelineStyle = BubbleRoomTimelineStyle(theme: theme)
|
||||
}
|
||||
|
||||
return roomTimelineStyle
|
||||
}
|
||||
}
|
|
@ -27,7 +27,6 @@
|
|||
@property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *userNameLabelTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewLeadingConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *descriptionContainerViewBottomConstraint;
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,345 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
@objcMembers
|
||||
class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private var theme: Theme
|
||||
|
||||
private var incomingColor: UIColor {
|
||||
return self.theme.colors.system
|
||||
}
|
||||
|
||||
private var outgoingColor: UIColor {
|
||||
return self.theme.colors.accent.withAlphaComponent(0.10)
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(theme: Theme) {
|
||||
self.theme = theme
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func updateLayoutIfNeeded(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) {
|
||||
|
||||
if cellData.isSenderCurrentUser {
|
||||
self.updateLayout(forOutgoingTextMessageCell: cell, andCellData: cellData)
|
||||
} else {
|
||||
self.updateLayout(forIncomingTextMessageCell: cell, andCellData: cellData)
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(forIncomingTextMessageCell cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) {
|
||||
|
||||
if let messageBubbleBackgroundView = cell.messageBubbleBackgroundView {
|
||||
|
||||
if self.canUseBubbleBackground(forCell: cell, withCellData: cellData) {
|
||||
|
||||
messageBubbleBackgroundView.isHidden = false
|
||||
|
||||
self.updateMessageBubbleBackgroundView(messageBubbleBackgroundView, withCell: cell, andCellData: cellData)
|
||||
} else {
|
||||
messageBubbleBackgroundView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(forOutgoingTextMessageCell cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) {
|
||||
|
||||
if let messageBubbleBackgroundView = cell.messageBubbleBackgroundView {
|
||||
|
||||
if self.canUseBubbleBackground(forCell: cell, withCellData: cellData) {
|
||||
|
||||
messageBubbleBackgroundView.isHidden = false
|
||||
|
||||
self.updateMessageBubbleBackgroundView(messageBubbleBackgroundView, withCell: cell, andCellData: cellData)
|
||||
} else {
|
||||
messageBubbleBackgroundView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setupLayout(forIncomingTextMessageCell cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
self.setupIncomingMessageTextViewMargins(for: cell)
|
||||
|
||||
self.addBubbleBackgroundViewToCell(cell, backgroundColor: self.incomingColor)
|
||||
|
||||
cell.setNeedsUpdateConstraints()
|
||||
}
|
||||
|
||||
func setupLayout(forOutgoingTextMessageCell cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
self.setupOutgoingMessageTextViewMargins(for: cell)
|
||||
|
||||
// Hide avatar view
|
||||
cell.pictureView?.isHidden = true
|
||||
|
||||
self.addBubbleBackgroundViewToCell(cell, backgroundColor: self.outgoingColor)
|
||||
|
||||
cell.setNeedsUpdateConstraints()
|
||||
}
|
||||
|
||||
func setupLayout(forOutgoingFileAttachmentCell cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
// Hide avatar view
|
||||
cell.pictureView?.isHidden = true
|
||||
|
||||
self.setupOutgoingFileAttachViewMargins(for: cell)
|
||||
}
|
||||
|
||||
// MARK: Themable
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
// MARK: Bubble background view
|
||||
|
||||
private func createBubbleBackgroundView(with backgroundColor: UIColor) -> RoomMessageBubbleBackgroundView {
|
||||
|
||||
let bubbleBackgroundView = RoomMessageBubbleBackgroundView()
|
||||
bubbleBackgroundView.backgroundColor = backgroundColor
|
||||
|
||||
return bubbleBackgroundView
|
||||
}
|
||||
|
||||
private func addBubbleBackgroundViewToCell(_ bubbleCell: MXKRoomBubbleTableViewCell, backgroundColor: UIColor) {
|
||||
|
||||
guard let messageTextView = bubbleCell.messageTextView else {
|
||||
return
|
||||
}
|
||||
|
||||
let topMargin: CGFloat = 0.0
|
||||
let leftMargin: CGFloat = 5.0
|
||||
let rightMargin: CGFloat = 45.0 // Add extra space for timestamp
|
||||
|
||||
let bubbleBackgroundView = self.createBubbleBackgroundView(with: backgroundColor)
|
||||
|
||||
bubbleCell.contentView.insertSubview(bubbleBackgroundView, at: 0)
|
||||
|
||||
let topAnchor = messageTextView.topAnchor
|
||||
let leadingAnchor = messageTextView.leadingAnchor
|
||||
let trailingAnchor = messageTextView.trailingAnchor
|
||||
|
||||
bubbleBackgroundView.updateHeight(messageTextView.frame.height)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
bubbleBackgroundView.topAnchor.constraint(equalTo: topAnchor, constant: topMargin),
|
||||
bubbleBackgroundView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: -leftMargin),
|
||||
bubbleBackgroundView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: rightMargin)
|
||||
])
|
||||
}
|
||||
|
||||
private func canUseBubbleBackground(forCell cell: MXKRoomBubbleTableViewCell, withCellData cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
|
||||
guard let firstComponent = cellData.getFirstBubbleComponentWithDisplay(), let firstEvent = firstComponent.event else {
|
||||
return false
|
||||
}
|
||||
|
||||
switch firstEvent.eventType {
|
||||
case .roomMessage:
|
||||
if let messageTypeString = firstEvent.content["msgtype"] as? String {
|
||||
|
||||
let messageType = MXMessageType(identifier: messageTypeString)
|
||||
|
||||
switch messageType {
|
||||
case .text, .emote, .file:
|
||||
return true
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private func getTextMessageHeight(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) -> CGFloat? {
|
||||
|
||||
guard let roomBubbleCellData = cellData as? RoomBubbleCellData,
|
||||
let lastBubbleComponent = cellData.getLastBubbleComponentWithDisplay(),
|
||||
let firstComponent = roomBubbleCellData.getFirstBubbleComponentWithDisplay() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let bubbleHeight: CGFloat
|
||||
|
||||
let lastEventId = lastBubbleComponent.event.eventId
|
||||
let lastMessageBottomPosition = cell.bottomPosition(ofEvent: lastEventId)
|
||||
|
||||
let firstEventId = firstComponent.event.eventId
|
||||
let firstMessageTopPosition = cell.topPosition(ofEvent: firstEventId)
|
||||
|
||||
let additionalContentHeight = roomBubbleCellData.additionalContentHeight
|
||||
|
||||
bubbleHeight = lastMessageBottomPosition - firstMessageTopPosition - additionalContentHeight
|
||||
|
||||
guard bubbleHeight >= 0 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return bubbleHeight
|
||||
}
|
||||
|
||||
// TODO: Improve text message height calculation
|
||||
// This method is closer to final result but lack of stability because of extra vertical space not handled here.
|
||||
// private func getTextMessageHeight(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) -> CGFloat? {
|
||||
//
|
||||
// guard let roomBubbleCellData = cellData as? RoomBubbleCellData,
|
||||
// let firstComponent = roomBubbleCellData.getFirstBubbleComponentWithDisplay() else {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// let bubbleHeight: CGFloat
|
||||
//
|
||||
// let componentIndex = cellData.bubbleComponentIndex(forEventId: firstComponent.event.eventId)
|
||||
//
|
||||
// let componentFrame = cell.componentFrameInContentView(for: componentIndex)
|
||||
//
|
||||
// bubbleHeight = componentFrame.height
|
||||
//
|
||||
// guard bubbleHeight >= 0 else {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// return bubbleHeight
|
||||
// }
|
||||
|
||||
private func getMessageBubbleBackgroundHeight(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) -> CGFloat? {
|
||||
|
||||
var finalBubbleHeight: CGFloat?
|
||||
let extraMargin: CGFloat = 4.0
|
||||
|
||||
if let bubbleHeight = self.getTextMessageHeight(for: cell, andCellData: cellData) {
|
||||
finalBubbleHeight = bubbleHeight + extraMargin
|
||||
|
||||
} else if let messageTextViewHeight = cell.messageTextView?.frame.height {
|
||||
|
||||
finalBubbleHeight = messageTextViewHeight + extraMargin
|
||||
}
|
||||
|
||||
return finalBubbleHeight
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
private func updateMessageBubbleBackgroundView(_ roomMessageBubbleBackgroundView: RoomMessageBubbleBackgroundView, withCell cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
|
||||
if let bubbleHeight = self.getMessageBubbleBackgroundHeight(for: cell, andCellData: cellData) {
|
||||
return roomMessageBubbleBackgroundView.updateHeight(bubbleHeight)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private func getIncomingMessageTextViewInsets(from bubbleCell: MXKRoomBubbleTableViewCell) -> UIEdgeInsets {
|
||||
|
||||
let messageViewMarginTop: CGFloat
|
||||
let messageViewMarginBottom: CGFloat = -2.0
|
||||
let messageViewMarginLeft: CGFloat = 3.0
|
||||
let messageViewMarginRight: CGFloat = 80
|
||||
|
||||
if bubbleCell.userNameLabel != nil {
|
||||
messageViewMarginTop = 10.0
|
||||
} else {
|
||||
messageViewMarginTop = 0.0
|
||||
}
|
||||
|
||||
let messageViewInsets = UIEdgeInsets(top: messageViewMarginTop, left: messageViewMarginLeft, bottom: messageViewMarginBottom, right: messageViewMarginRight)
|
||||
|
||||
return messageViewInsets
|
||||
}
|
||||
|
||||
// MARK: Text message
|
||||
|
||||
private func setupIncomingMessageTextViewMargins(for cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
guard cell.messageTextView != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
let messageViewInsets = self.getIncomingMessageTextViewInsets(from: cell)
|
||||
|
||||
cell.msgTextViewBottomConstraint.constant += messageViewInsets.bottom
|
||||
cell.msgTextViewTopConstraint.constant += messageViewInsets.top
|
||||
cell.msgTextViewLeadingConstraint.constant += messageViewInsets.left
|
||||
cell.msgTextViewTrailingConstraint.constant += messageViewInsets.right
|
||||
}
|
||||
|
||||
private func setupOutgoingMessageTextViewMargins(for cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
guard let messageTextView = cell.messageTextView else {
|
||||
return
|
||||
}
|
||||
|
||||
let contentView = cell.contentView
|
||||
|
||||
let leftMargin: CGFloat = 80.0
|
||||
let rightMargin: CGFloat = 78.0
|
||||
let bottomMargin: CGFloat = -2.0
|
||||
|
||||
cell.msgTextViewLeadingConstraint.isActive = false
|
||||
cell.msgTextViewTrailingConstraint.isActive = false
|
||||
|
||||
let leftConstraint = messageTextView.leadingAnchor.constraint(greaterThanOrEqualTo: contentView.leadingAnchor, constant: leftMargin)
|
||||
|
||||
let rightConstraint = messageTextView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -rightMargin)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
leftConstraint,
|
||||
rightConstraint
|
||||
])
|
||||
|
||||
cell.msgTextViewLeadingConstraint = leftConstraint
|
||||
cell.msgTextViewTrailingConstraint = rightConstraint
|
||||
|
||||
cell.msgTextViewBottomConstraint.constant += bottomMargin
|
||||
}
|
||||
|
||||
private func setupOutgoingFileAttachViewMargins(for cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
guard let attachmentView = cell.attachmentView else {
|
||||
return
|
||||
}
|
||||
|
||||
let contentView = cell.contentView
|
||||
|
||||
// TODO: Use constants
|
||||
// Same as URL preview
|
||||
let rightMargin: CGFloat = 34.0
|
||||
|
||||
if let attachViewLeadingConstraint = cell.attachViewLeadingConstraint {
|
||||
attachViewLeadingConstraint.isActive = false
|
||||
cell.attachViewLeadingConstraint = nil
|
||||
}
|
||||
|
||||
let rightConstraint = attachmentView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -rightMargin)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
rightConstraint
|
||||
])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator {
|
||||
|
||||
override func addTimestampLabelIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
guard self.canShowTimestamp(forCellData: cellData) else {
|
||||
return
|
||||
}
|
||||
|
||||
self.addTimestampLabel(toCell: cell, cellData: cellData)
|
||||
}
|
||||
|
||||
override func addTimestampLabel(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
// If cell contains a bubble background, add the timestamp inside of it
|
||||
if let bubbleBackgroundView = cell.messageBubbleBackgroundView, bubbleBackgroundView.isHidden == false {
|
||||
|
||||
let componentIndex = cellData.mostRecentComponentIndex
|
||||
|
||||
guard let bubbleComponents = cellData.bubbleComponents,
|
||||
componentIndex < bubbleComponents.count else {
|
||||
return
|
||||
}
|
||||
|
||||
let component = bubbleComponents[componentIndex]
|
||||
|
||||
let timestampLabel = self.createTimestampLabel(cellData: cellData,
|
||||
bubbleComponent: component,
|
||||
viewTag: componentIndex)
|
||||
timestampLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
cell.addTemporarySubview(timestampLabel)
|
||||
|
||||
bubbleBackgroundView.addSubview(timestampLabel)
|
||||
|
||||
let rightMargin: CGFloat = 8.0
|
||||
let bottomMargin: CGFloat = 4.0
|
||||
|
||||
let trailingConstraint = timestampLabel.trailingAnchor.constraint(equalTo: bubbleBackgroundView.trailingAnchor, constant: -rightMargin)
|
||||
|
||||
let bottomConstraint = timestampLabel.bottomAnchor.constraint(equalTo: bubbleBackgroundView.bottomAnchor, constant: -bottomMargin)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
trailingConstraint,
|
||||
bottomConstraint
|
||||
])
|
||||
} else {
|
||||
super.addTimestampLabel(toCell: cell, cellData: cellData)
|
||||
}
|
||||
}
|
||||
|
||||
override func addReactionView(_ reactionsView: BubbleReactionsView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData, contentViewPositionY: CGFloat, upperDecorationView: UIView?) {
|
||||
|
||||
cell.addTemporarySubview(reactionsView)
|
||||
|
||||
if let reactionsDisplayable = cell as? BubbleCellReactionsDisplayable {
|
||||
reactionsDisplayable.addReactionsView(reactionsView)
|
||||
return
|
||||
}
|
||||
|
||||
reactionsView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
cellContentView.addSubview(reactionsView)
|
||||
|
||||
// TODO: Use constants
|
||||
let topMargin: CGFloat = 4.0
|
||||
let leftMargin: CGFloat
|
||||
let rightMargin: CGFloat
|
||||
|
||||
// Outgoing message
|
||||
if cellData.isSenderCurrentUser {
|
||||
reactionsView.alignment = .right
|
||||
|
||||
// TODO: Use constants
|
||||
var outgointLeftMargin: CGFloat = 80.0
|
||||
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
outgointLeftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
leftMargin = outgointLeftMargin
|
||||
|
||||
// TODO: Use constants
|
||||
rightMargin = 33
|
||||
} else {
|
||||
// Incoming message
|
||||
|
||||
var incomingLeftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
incomingLeftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
leftMargin = incomingLeftMargin - 6.0
|
||||
|
||||
// TODO: Use constants
|
||||
let messageViewMarginRight: CGFloat = 42.0
|
||||
|
||||
rightMargin = messageViewMarginRight
|
||||
}
|
||||
|
||||
let leadingConstraint = reactionsView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin)
|
||||
|
||||
let trailingConstraint = reactionsView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -rightMargin)
|
||||
|
||||
let topConstraint: NSLayoutConstraint
|
||||
if let upperDecorationView = upperDecorationView {
|
||||
topConstraint = reactionsView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor, constant: topMargin)
|
||||
} else {
|
||||
topConstraint = reactionsView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: contentViewPositionY + topMargin)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
leadingConstraint,
|
||||
trailingConstraint,
|
||||
topConstraint
|
||||
])
|
||||
}
|
||||
|
||||
override func addURLPreviewView(_ urlPreviewView: URLPreviewView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat) {
|
||||
|
||||
cell.addTemporarySubview(urlPreviewView)
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
urlPreviewView.translatesAutoresizingMaskIntoConstraints = false
|
||||
urlPreviewView.availableWidth = cellData.maxTextViewWidth
|
||||
cellContentView.addSubview(urlPreviewView)
|
||||
|
||||
let leadingOrTrailingConstraint: NSLayoutConstraint
|
||||
|
||||
// Outgoing message
|
||||
if cellData.isSenderCurrentUser {
|
||||
|
||||
// TODO: Use constants
|
||||
let rightMargin: CGFloat = 34.0
|
||||
|
||||
leadingOrTrailingConstraint = urlPreviewView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -rightMargin)
|
||||
} else {
|
||||
// Incoming message
|
||||
|
||||
var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
leftMargin-=5.0
|
||||
|
||||
leadingOrTrailingConstraint = urlPreviewView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin)
|
||||
}
|
||||
|
||||
let topMargin = contentViewPositionY + RoomBubbleCellLayout.urlPreviewViewTopMargin + RoomBubbleCellLayout.reactionsViewTopMargin
|
||||
|
||||
// Set the preview view's origin
|
||||
NSLayoutConstraint.activate([
|
||||
leadingOrTrailingConstraint,
|
||||
urlPreviewView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: topMargin)
|
||||
])
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func createTimestampLabel(cellData: MXKRoomBubbleCellData, bubbleComponent: MXKRoomBubbleComponent, viewTag: Int) -> UILabel {
|
||||
|
||||
let timeLabel = UILabel()
|
||||
|
||||
timeLabel.text = cellData.eventFormatter.timeString(from: bubbleComponent.date)
|
||||
timeLabel.textAlignment = .right
|
||||
timeLabel.textColor = ThemeService.shared().theme.textSecondaryColor
|
||||
timeLabel.font = UIFont.systemFont(ofSize: 11, weight: .light)
|
||||
timeLabel.adjustsFontSizeToFitWidth = true
|
||||
timeLabel.tag = viewTag
|
||||
timeLabel.accessibilityIdentifier = "timestampLabel"
|
||||
|
||||
return timeLabel
|
||||
}
|
||||
|
||||
private func canShowTimestamp(forCellData cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
|
||||
guard cellData.isCollapsableAndCollapsed == false else {
|
||||
return false
|
||||
}
|
||||
|
||||
guard let firstComponent = cellData.getFirstBubbleComponentWithDisplay(), let firstEvent = firstComponent.event else {
|
||||
return false
|
||||
}
|
||||
|
||||
switch firstEvent.eventType {
|
||||
case .roomMessage:
|
||||
if let messageTypeString = firstEvent.content["msgtype"] as? String {
|
||||
|
||||
let messageType = MXMessageType(identifier: messageTypeString)
|
||||
|
||||
switch messageType {
|
||||
case .text, .emote, .file:
|
||||
return true
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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 "PlainRoomTimelineCellProvider.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface BubbleRoomTimelineCellProvider : PlainRoomTimelineCellProvider
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// 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 "BubbleRoomTimelineCellProvider.h"
|
||||
|
||||
#pragma mark - Imports
|
||||
|
||||
#pragma mark Text message
|
||||
|
||||
// Outgoing
|
||||
|
||||
// Clear
|
||||
#import "RoomOutgoingTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
|
||||
// Encrypted
|
||||
|
||||
#import "RoomOutgoingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
|
||||
#pragma mark Attachment
|
||||
|
||||
// Outgoing
|
||||
|
||||
// Clear
|
||||
#import "RoomOutgoingAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
// Encrypted
|
||||
#import "RoomOutgoingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
@implementation BubbleRoomTimelineCellProvider
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingTextMessageCellsMapping
|
||||
{
|
||||
// Hide sender info and avatar for bubble outgoing messages
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessage) : RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderInfo) : RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitle) : RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderName) : RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitleWithoutSenderName) : RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncrypted) : RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderInfo) : RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitle) : RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderName) : RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitleWithoutSenderName) : RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingAttachmentCellsMapping
|
||||
{
|
||||
// Hide sender info and avatar for bubble outgoing file attachment
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachment) : RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentWithoutSenderInfo) : RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentWithPaginationTitle) : RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncrypted) : RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithoutSenderInfo) : RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithPaginationTitle) : RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
class BubbleRoomTimelineStyle: RoomTimelineStyle {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var theme: Theme
|
||||
|
||||
// MARK: Public
|
||||
|
||||
let identifier: RoomTimelineStyleIdentifier
|
||||
|
||||
let cellLayoutUpdater: RoomCellLayoutUpdating?
|
||||
|
||||
let cellProvider: RoomTimelineCellProvider
|
||||
|
||||
let cellDecorator: RoomTimelineCellDecorator
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(theme: Theme) {
|
||||
self.theme = theme
|
||||
self.identifier = .bubble
|
||||
self.cellLayoutUpdater = BubbleRoomCellLayoutUpdater(theme: theme)
|
||||
self.cellProvider = BubbleRoomTimelineCellProvider()
|
||||
self.cellDecorator = BubbleRoomTimelineCellDecorator()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func canAddEvent(_ event: MXEvent, and roomState: MXRoomState, to cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func applySelectedStyleIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
// Check whether the selected event belongs to this bubble
|
||||
let selectedComponentIndex = cellData.selectedComponentIndex
|
||||
if selectedComponentIndex != NSNotFound {
|
||||
|
||||
cell.selectComponent(UInt(selectedComponentIndex),
|
||||
showEditButton: false,
|
||||
showTimestamp: false)
|
||||
|
||||
self.cellDecorator.addTimestampLabel(toCell: cell, cellData: cellData)
|
||||
} else {
|
||||
cell.blurred = true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Themable
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
self.cellLayoutUpdater?.update(theme: theme)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
extension MXKRoomBubbleTableViewCell {
|
||||
|
||||
// Enables to get existing bubble background view
|
||||
// This used while there is no dedicated cell classes for bubble style
|
||||
var messageBubbleBackgroundView: RoomMessageBubbleBackgroundView? {
|
||||
|
||||
let foundView = self.contentView.subviews.first { view in
|
||||
return view is RoomMessageBubbleBackgroundView
|
||||
}
|
||||
return foundView as? RoomMessageBubbleBackgroundView
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
class RoomMessageBubbleBackgroundView: UIView {
|
||||
|
||||
// MARK: - Constant
|
||||
|
||||
private enum Constants {
|
||||
static let cornerRadius: CGFloat = 12.0
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private var heightConstraint: NSLayoutConstraint?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: CGRect.zero)
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.layer.masksToBounds = true
|
||||
self.layer.cornerRadius = Constants.cornerRadius
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
@discardableResult
|
||||
func updateHeight(_ height: CGFloat) -> Bool {
|
||||
if let heightConstraint = self.heightConstraint {
|
||||
|
||||
guard heightConstraint.constant != height else {
|
||||
return false
|
||||
}
|
||||
|
||||
heightConstraint.constant = height
|
||||
|
||||
return true
|
||||
} else {
|
||||
let heightConstraint = self.heightAnchor.constraint(equalToConstant: height)
|
||||
heightConstraint.isActive = true
|
||||
self.heightConstraint = heightConstraint
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
@objcMembers
|
||||
class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator {
|
||||
|
||||
func addTimestampLabelIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
guard cellData.containsLastMessage && cellData.isCollapsableAndCollapsed == false else {
|
||||
return
|
||||
}
|
||||
|
||||
// Display timestamp of the last message
|
||||
self.addTimestampLabel(toCell: cell, cellData: cellData)
|
||||
}
|
||||
|
||||
func addTimestampLabel(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
cell.addTimestampLabel(forComponent: UInt(cellData.mostRecentComponentIndex))
|
||||
}
|
||||
|
||||
func addURLPreviewView(_ urlPreviewView: URLPreviewView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat) {
|
||||
cell.addTemporarySubview(urlPreviewView)
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
urlPreviewView.translatesAutoresizingMaskIntoConstraints = false
|
||||
urlPreviewView.availableWidth = cellData.maxTextViewWidth
|
||||
cellContentView.addSubview(urlPreviewView)
|
||||
|
||||
var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
let topMargin = contentViewPositionY + RoomBubbleCellLayout.urlPreviewViewTopMargin + RoomBubbleCellLayout.reactionsViewTopMargin
|
||||
|
||||
// Set the preview view's origin
|
||||
NSLayoutConstraint.activate([
|
||||
urlPreviewView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin),
|
||||
urlPreviewView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: topMargin)
|
||||
])
|
||||
}
|
||||
|
||||
func addReactionView(_ reactionsView: BubbleReactionsView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?) {
|
||||
|
||||
cell.addTemporarySubview(reactionsView)
|
||||
|
||||
if let reactionsDisplayable = cell as? BubbleCellReactionsDisplayable {
|
||||
reactionsDisplayable.addReactionsView(reactionsView)
|
||||
} else {
|
||||
reactionsView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
cellContentView.addSubview(reactionsView)
|
||||
|
||||
var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
let rightMargin = RoomBubbleCellLayout.reactionsViewRightMargin
|
||||
let topMargin = RoomBubbleCellLayout.reactionsViewTopMargin
|
||||
|
||||
// The top constraint may need to include the URL preview view
|
||||
let topConstraint: NSLayoutConstraint
|
||||
if let upperDecorationView = upperDecorationView {
|
||||
topConstraint = reactionsView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor, constant: topMargin)
|
||||
} else {
|
||||
topConstraint = reactionsView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: contentViewPositionY + topMargin)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
reactionsView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin),
|
||||
reactionsView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -rightMargin),
|
||||
topConstraint
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
func addReadReceiptsView(_ readReceiptsView: MXKReceiptSendersContainer,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?) {
|
||||
|
||||
cell.addTemporarySubview(readReceiptsView)
|
||||
|
||||
if let readReceiptsDisplayable = cell as? BubbleCellReadReceiptsDisplayable {
|
||||
readReceiptsDisplayable.addReadReceiptsView(readReceiptsView)
|
||||
} else {
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
cellContentView.addSubview(readReceiptsView)
|
||||
|
||||
// Force receipts container size
|
||||
let widthConstraint = readReceiptsView.widthAnchor.constraint(equalToConstant: RoomBubbleCellLayout.readReceiptsViewWidth)
|
||||
let heightConstraint = readReceiptsView.heightAnchor.constraint(equalToConstant: RoomBubbleCellLayout.readReceiptsViewHeight)
|
||||
|
||||
// Force receipts container position
|
||||
let trailingConstraint = readReceiptsView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -RoomBubbleCellLayout.readReceiptsViewRightMargin)
|
||||
|
||||
let topMargin = RoomBubbleCellLayout.readReceiptsViewTopMargin
|
||||
|
||||
let topConstraint: NSLayoutConstraint
|
||||
if let upperDecorationView = upperDecorationView {
|
||||
topConstraint = readReceiptsView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor, constant: topMargin)
|
||||
} else {
|
||||
topConstraint = readReceiptsView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: contentViewPositionY + topMargin)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
widthConstraint,
|
||||
heightConstraint,
|
||||
trailingConstraint,
|
||||
topConstraint
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
func addSendStatusView(toCell cell: MXKRoomBubbleTableViewCell, withFailedEventIds failedEventIds: Set<AnyHashable>) {
|
||||
cell.updateTickView(withFailedEventIds: failedEventIds)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// 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 "RoomTimelineCellProvider.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface PlainRoomTimelineCellProvider: NSObject<RoomTimelineCellProvider>
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingTextMessageCellsMapping;
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingAttachmentCellsMapping;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,453 @@
|
|||
//
|
||||
// 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 "PlainRoomTimelineCellProvider.h"
|
||||
|
||||
#import "MXKRoomBubbleTableViewCell+Riot.h"
|
||||
|
||||
#import "RoomEmptyBubbleCell.h"
|
||||
|
||||
#import "RoomIncomingTextMsgBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomIncomingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomOutgoingTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
|
||||
#import "RoomOutgoingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomMembershipBubbleCell.h"
|
||||
#import "RoomMembershipWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomMembershipCollapsedBubbleCell.h"
|
||||
#import "RoomMembershipCollapsedWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomMembershipExpandedBubbleCell.h"
|
||||
#import "RoomMembershipExpandedWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomCreationWithPaginationCollapsedBubbleCell.h"
|
||||
#import "RoomCreationCollapsedBubbleCell.h"
|
||||
|
||||
#import "RoomSelectedStickerBubbleCell.h"
|
||||
#import "RoomPredecessorBubbleCell.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@interface PlainRoomTimelineCellProvider()
|
||||
|
||||
@property (nonatomic, strong) NSDictionary<NSNumber*, Class>* cellClasses;
|
||||
|
||||
@end
|
||||
|
||||
@implementation PlainRoomTimelineCellProvider
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)registerCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Text message
|
||||
|
||||
[self registerIncomingTextMessageCellsForTableView:tableView];
|
||||
|
||||
[self registerOutgoingTextMessageCellsForTableView:tableView];
|
||||
|
||||
// Attachment cells
|
||||
|
||||
[self registerIncomingAttachmentCellsForTableView:tableView];
|
||||
|
||||
[self registerOutgoingAttachmentCellsForTableView:tableView];
|
||||
|
||||
// Other cells
|
||||
|
||||
[self registerMembershipCellsForTableView:tableView];
|
||||
|
||||
[self registerKeyVerificationCellsForTableView:tableView];
|
||||
|
||||
[self registerRoomCreationCellsForTableView:tableView];
|
||||
|
||||
[self registerCallCellsForTableView:tableView];
|
||||
|
||||
[self registerVoiceMessageCellsForTableView:tableView];
|
||||
|
||||
[self registerPollCellsForTableView:tableView];
|
||||
|
||||
[self registerLocationCellsForTableView:tableView];
|
||||
|
||||
[tableView registerClass:RoomEmptyBubbleCell.class forCellReuseIdentifier:RoomEmptyBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[tableView registerClass:RoomSelectedStickerBubbleCell.class forCellReuseIdentifier:RoomSelectedStickerBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[tableView registerClass:RoomPredecessorBubbleCell.class forCellReuseIdentifier:RoomPredecessorBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[tableView registerClass:RoomCreationIntroCell.class forCellReuseIdentifier:RoomCreationIntroCell.defaultReuseIdentifier];
|
||||
|
||||
[tableView registerNib:RoomTypingBubbleCell.nib forCellReuseIdentifier:RoomTypingBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (Class<MXKCellRendering>)cellViewClassForCellIdentifier:(RoomTimelineCellIdentifier)identifier
|
||||
{
|
||||
if (self.cellClasses == nil)
|
||||
{
|
||||
self.cellClasses = [self buildCellClasses];
|
||||
}
|
||||
|
||||
Class cellViewClass = self.cellClasses[@(identifier)];
|
||||
|
||||
|
||||
return cellViewClass;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
#pragma mark Cell registration
|
||||
|
||||
- (void)registerIncomingTextMessageCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Clear
|
||||
|
||||
[tableView registerClass:RoomIncomingTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Encrypted
|
||||
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerOutgoingTextMessageCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Clear
|
||||
|
||||
[tableView registerClass:RoomOutgoingTextMsgBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Encrypted
|
||||
|
||||
[tableView registerClass:RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerIncomingAttachmentCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Clear
|
||||
|
||||
[tableView registerClass:RoomIncomingAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Encrypted
|
||||
|
||||
[tableView registerClass:RoomIncomingEncryptedAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerOutgoingAttachmentCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Clear
|
||||
|
||||
[tableView registerClass:RoomOutgoingAttachmentBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Encrypted
|
||||
|
||||
[tableView registerClass:RoomOutgoingEncryptedAttachmentBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerMembershipCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:RoomMembershipBubbleCell.class forCellReuseIdentifier:RoomMembershipBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipCollapsedBubbleCell.class forCellReuseIdentifier:RoomMembershipCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipCollapsedWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipCollapsedWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipExpandedBubbleCell.class forCellReuseIdentifier:RoomMembershipExpandedBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipExpandedWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipExpandedWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerKeyVerificationCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:KeyVerificationIncomingRequestApprovalBubbleCell.class forCellReuseIdentifier:KeyVerificationIncomingRequestApprovalBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationRequestStatusBubbleCell.class forCellReuseIdentifier:KeyVerificationRequestStatusBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationRequestStatusWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationRequestStatusWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationConclusionBubbleCell.class forCellReuseIdentifier:KeyVerificationConclusionBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationConclusionWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationConclusionWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerRoomCreationCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:RoomCreationCollapsedBubbleCell.class forCellReuseIdentifier:RoomCreationCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomCreationWithPaginationCollapsedBubbleCell.class forCellReuseIdentifier:RoomCreationWithPaginationCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerCallCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:RoomDirectCallStatusBubbleCell.class forCellReuseIdentifier:RoomDirectCallStatusBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomGroupCallStatusBubbleCell.class forCellReuseIdentifier:RoomGroupCallStatusBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerVoiceMessageCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:VoiceMessageBubbleCell.class forCellReuseIdentifier:VoiceMessageBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:VoiceMessageWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:VoiceMessageWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:VoiceMessageWithPaginationTitleBubbleCell.class forCellReuseIdentifier:VoiceMessageWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerPollCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:PollBubbleCell.class forCellReuseIdentifier:PollBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:PollWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:PollWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:PollWithPaginationTitleBubbleCell.class forCellReuseIdentifier:PollWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerLocationCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:LocationBubbleCell.class forCellReuseIdentifier:LocationBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:LocationWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:LocationWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:LocationWithPaginationTitleBubbleCell.class forCellReuseIdentifier:LocationWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
#pragma mark Cell class association
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)buildCellClasses
|
||||
{
|
||||
NSMutableDictionary<NSNumber*, Class>* cellClasses = [NSMutableDictionary dictionary];
|
||||
|
||||
// Text message
|
||||
|
||||
NSDictionary *incomingTextMessageCellsMapping = [self incomingTextMessageCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:incomingTextMessageCellsMapping];
|
||||
|
||||
NSDictionary *outgoingTextMessageCellsMapping = [self outgoingTextMessageCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:outgoingTextMessageCellsMapping];
|
||||
|
||||
// Attachment
|
||||
|
||||
NSDictionary *incomingAttachmentCellsMapping = [self incomingAttachmentCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:incomingAttachmentCellsMapping];
|
||||
|
||||
NSDictionary *outgoingAttachmentCellsMapping = [self outgoingAttachmentCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:outgoingAttachmentCellsMapping];
|
||||
|
||||
// Other cells
|
||||
|
||||
NSDictionary *roomMembershipCellsMapping = [self membershipCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:roomMembershipCellsMapping];
|
||||
|
||||
NSDictionary *keyVerificationCellsMapping = [self keyVerificationCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:keyVerificationCellsMapping];
|
||||
|
||||
NSDictionary *roomCreationCellsMapping = [self roomCreationCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:roomCreationCellsMapping];
|
||||
|
||||
NSDictionary *callCellsMapping = [self callCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:callCellsMapping];
|
||||
|
||||
NSDictionary *voiceMessageCellsMapping = [self voiceMessageCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:voiceMessageCellsMapping];
|
||||
|
||||
NSDictionary *pollCellsMapping = [self pollCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:pollCellsMapping];
|
||||
|
||||
NSDictionary *locationCellsMapping = [self locationCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:locationCellsMapping];
|
||||
|
||||
NSDictionary *othersCells = @{
|
||||
@(RoomTimelineCellIdentifierEmpty) : RoomEmptyBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierSelectedSticker) : RoomSelectedStickerBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierRoomPredecessor) : RoomPredecessorBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierRoomCreationIntro) : RoomCreationIntroCell.class,
|
||||
@(RoomTimelineCellIdentifierTyping) : RoomTypingBubbleCell.class,
|
||||
};
|
||||
[cellClasses addEntriesFromDictionary:othersCells];
|
||||
|
||||
return [cellClasses copy];
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)incomingTextMessageCellsMapping
|
||||
{
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessage) : RoomIncomingTextMsgBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderInfo) : RoomIncomingTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitle) : RoomIncomingTextMsgWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderName) : RoomIncomingTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitleWithoutSenderName) : RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncrypted) : RoomIncomingEncryptedTextMsgBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderInfo) : RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitle) : RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderName) : RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitleWithoutSenderName) : RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingTextMessageCellsMapping
|
||||
{
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessage) : RoomOutgoingTextMsgBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderInfo) : RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitle) : RoomOutgoingTextMsgWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderName) : RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitleWithoutSenderName) : RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncrypted) : RoomOutgoingEncryptedTextMsgBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderInfo) : RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitle) : RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderName) : RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitleWithoutSenderName) : RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)incomingAttachmentCellsMapping
|
||||
{
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierIncomingAttachment) : RoomIncomingAttachmentBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentWithoutSenderInfo) : RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentWithPaginationTitle) : RoomIncomingAttachmentWithPaginationTitleBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentEncrypted) : RoomIncomingEncryptedAttachmentBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithoutSenderInfo) : RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithPaginationTitle) : RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingAttachmentCellsMapping
|
||||
{
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachment) : RoomOutgoingAttachmentBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentWithoutSenderInfo) : RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentWithPaginationTitle) : RoomOutgoingAttachmentWithPaginationTitleBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncrypted) : RoomOutgoingEncryptedAttachmentBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithoutSenderInfo) : RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithPaginationTitle) : RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)membershipCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierMembership) : RoomMembershipBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipWithPaginationTitle) : RoomMembershipWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipCollapsed) : RoomMembershipCollapsedBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipCollapsedWithPaginationTitle) : RoomMembershipCollapsedWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipExpanded) : RoomMembershipExpandedBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipExpandedWithPaginationTitle) : RoomMembershipExpandedWithPaginationTitleBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)keyVerificationCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierKeyVerificationIncomingRequestApproval) : KeyVerificationIncomingRequestApprovalBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationIncomingRequestApprovalWithPaginationTitle) : KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationRequestStatus) : KeyVerificationRequestStatusBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationRequestStatusWithPaginationTitle) : KeyVerificationRequestStatusWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationConclusion) : KeyVerificationConclusionBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationConclusionWithPaginationTitle) : KeyVerificationConclusionWithPaginationTitleBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)roomCreationCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierRoomCreationCollapsed) : RoomCreationCollapsedBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierRoomCreationCollapsedWithPaginationTitle) : RoomCreationWithPaginationCollapsedBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)callCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierDirectCallStatus) : RoomDirectCallStatusBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierGroupCallStatus) : RoomGroupCallStatusBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)voiceMessageCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierVoiceMessage) : VoiceMessageBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierVoiceMessageWithoutSenderInfo) : VoiceMessageWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierVoiceMessageWithPaginationTitle) : VoiceMessageWithPaginationTitleBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)pollCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierPoll) : PollBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierPollWithoutSenderInfo) : PollWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierPollWithPaginationTitle) : PollWithPaginationTitleBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)locationCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierLocation) : LocationBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierLocationWithoutSenderInfo) : LocationWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierLocationWithPaginationTitle) : LocationWithPaginationTitleBubbleCell.class
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@end
|
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
class PlainRoomTimelineStyle: RoomTimelineStyle {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var theme: Theme
|
||||
|
||||
// MARK: Public
|
||||
|
||||
let identifier: RoomTimelineStyleIdentifier
|
||||
|
||||
let cellLayoutUpdater: RoomCellLayoutUpdating?
|
||||
|
||||
let cellProvider: RoomTimelineCellProvider
|
||||
|
||||
let cellDecorator: RoomTimelineCellDecorator
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(theme: Theme) {
|
||||
self.theme = theme
|
||||
self.identifier = .plain
|
||||
self.cellLayoutUpdater = nil
|
||||
self.cellProvider = PlainRoomTimelineCellProvider()
|
||||
self.cellDecorator = PlainRoomTimelineCellDecorator()
|
||||
}
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
func canAddEvent(_ event: MXEvent, and roomState: MXRoomState, to cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func applySelectedStyleIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
// Check whether the selected event belongs to this bubble
|
||||
let selectedComponentIndex = cellData.selectedComponentIndex
|
||||
if selectedComponentIndex != NSNotFound {
|
||||
|
||||
let showTimestamp = cellData.showTimestampForSelectedComponent
|
||||
|
||||
cell.selectComponent(UInt(selectedComponentIndex),
|
||||
showEditButton: false,
|
||||
showTimestamp: showTimestamp)
|
||||
} else {
|
||||
cell.blurred = true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Themable
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
/// Enables to setup or update a room timeline cell view
|
||||
@objc
|
||||
protocol RoomCellLayoutUpdating: Themable {
|
||||
|
||||
func updateLayoutIfNeeded(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData)
|
||||
|
||||
func setupLayout(forIncomingTextMessageCell cell: MXKRoomBubbleTableViewCell)
|
||||
|
||||
func setupLayout(forOutgoingTextMessageCell cell: MXKRoomBubbleTableViewCell)
|
||||
|
||||
func setupLayout(forOutgoingFileAttachmentCell cell: MXKRoomBubbleTableViewCell)
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
/// RoomTimelineCellDecorator enables to add decoration on a cell (reactions, read receipts, timestamp, URL preview).
|
||||
@objc
|
||||
protocol RoomTimelineCellDecorator {
|
||||
|
||||
func addTimestampLabelIfNeeded(toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData)
|
||||
|
||||
func addTimestampLabel(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData)
|
||||
|
||||
func addURLPreviewView(_ urlPreviewView: URLPreviewView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat)
|
||||
|
||||
func addReactionView(_ reactionsView: BubbleReactionsView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?)
|
||||
|
||||
func addReadReceiptsView(_ readReceiptsView: MXKReceiptSendersContainer,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?)
|
||||
|
||||
func addSendStatusView(toCell cell: MXKRoomBubbleTableViewCell,
|
||||
withFailedEventIds failedEventIds: Set<AnyHashable>)
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// 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 <UIKit/UIKit.h>
|
||||
|
||||
#import "RoomTimelineCellIdentifier.h"
|
||||
#import "MXKCellRendering.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Enables to register and provide room timeline cells
|
||||
@protocol RoomTimelineCellProvider <NSObject>
|
||||
|
||||
/// Register timeline cells for the given table view
|
||||
- (void)registerCellsForTableView:(UITableView*)tableView;
|
||||
|
||||
/// Get timeline cell class from cell identifier
|
||||
- (Class<MXKCellRendering>)cellViewClassForCellIdentifier:(RoomTimelineCellIdentifier)identifier;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// 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 MatrixSDK
|
||||
|
||||
/// RoomTimelineStyle describes a room timeline style used to customize timeline appearance
|
||||
@objc
|
||||
protocol RoomTimelineStyle: Themable {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// Style identifier
|
||||
var identifier: RoomTimelineStyleIdentifier { get }
|
||||
|
||||
/// Update layout if needed for cells provided by the cell provider
|
||||
var cellLayoutUpdater: RoomCellLayoutUpdating? { get }
|
||||
|
||||
/// Register and provide timeline cells
|
||||
var cellProvider: RoomTimelineCellProvider { get }
|
||||
|
||||
/// Handle cell decorations (reactions, read receipts, URL preview, …)
|
||||
var cellDecorator: RoomTimelineCellDecorator { get }
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
/// Indicate to merge or not event in timeline
|
||||
func canAddEvent(_ event: MXEvent, and roomState: MXRoomState, to cellData: MXKRoomBubbleCellData) -> Bool
|
||||
|
||||
/// Apply selected or blurred style on cell
|
||||
func applySelectedStyleIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData)
|
||||
}
|
|
@ -17,7 +17,8 @@
|
|||
import Foundation
|
||||
|
||||
/// Represents the room timeline style identifiers available
|
||||
enum RoomTimelineStyleIdentifier {
|
||||
@objc
|
||||
enum RoomTimelineStyleIdentifier: Int {
|
||||
case plain
|
||||
case bubble
|
||||
}
|
||||
|
|
|
@ -16,6 +16,17 @@
|
|||
|
||||
#import "MXKRoomIncomingTextMsgBubbleCell.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation MXKRoomIncomingTextMsgBubbleCell
|
||||
|
||||
- (void)setupViews
|
||||
{
|
||||
[super setupViews];
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
[timelineConfiguration.currentStyle.cellLayoutUpdater setupLayoutForIncomingTextMessageCell:self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -16,6 +16,18 @@
|
|||
|
||||
#import "MXKRoomOutgoingTextMsgBubbleCell.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation MXKRoomOutgoingTextMsgBubbleCell
|
||||
|
||||
- (void)setupViews
|
||||
{
|
||||
[super setupViews];
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
[timelineConfiguration.currentStyle.cellLayoutUpdater setupLayoutForOutgoingTextMessageCell:self];
|
||||
}
|
||||
|
||||
|
||||
@end
|
|
@ -3898,6 +3898,13 @@ TableViewSectionsDelegate>
|
|||
- (void)toggleEnableRoomMessageBubbles:(UISwitch *)sender
|
||||
{
|
||||
RiotSettings.shared.roomScreenEnableMessageBubbles = sender.isOn;
|
||||
|
||||
[[RoomTimelineConfiguration shared] updateStyleWithIdentifier:RiotSettings.shared.roomTimelineStyleIdentifier];
|
||||
|
||||
// Close all room data sources
|
||||
// Be sure to use new room timeline style configurations
|
||||
MXKRoomDataSourceManager *roomDataSourceManager = [MXKRoomDataSourceManager sharedManagerForMatrixSession:self.mainSession];
|
||||
[roomDataSourceManager reset];
|
||||
}
|
||||
|
||||
#pragma mark - TextField listener
|
||||
|
|
|
@ -97,8 +97,13 @@ final class SideMenuViewModel: SideMenuViewModelType {
|
|||
return
|
||||
}
|
||||
|
||||
let sideMenuItems: [SideMenuItem] = [
|
||||
.inviteFriends,
|
||||
var sideMenuItems: [SideMenuItem] = []
|
||||
|
||||
if BuildSettings.sideMenuShowInviteFriends {
|
||||
sideMenuItems += [.inviteFriends]
|
||||
}
|
||||
|
||||
sideMenuItems += [
|
||||
.settings,
|
||||
.help,
|
||||
.feedback
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue