Merge branch 'develop' into spaces

# Conflicts:
#	Riot/Modules/Common/Avatar/AvatarViewDataProtocol.swift
#	Riot/Modules/Common/Recents/RecentsViewController.m
#	Riot/Modules/Home/Views/RoomCollectionViewCell.m
#	Riot/Modules/TabBar/TabBarCoordinator.swift
This commit is contained in:
Gil Eluard
2021-09-15 14:42:04 +02:00
366 changed files with 11801 additions and 3234 deletions
@@ -1,100 +0,0 @@
//
// 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
@objc protocol RoomNotificationSettingsCoordinatorBridgePresenterDelegate {
func roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(_ coordinatorBridgePresenter: RoomNotificationSettingsCoordinatorBridgePresenter)
}
/// RoomNotificationSettingsCoordinatorBridgePresenter enables to start RoomNotificationSettingsCoordinator from a view controller.
/// This bridge is used while waiting for global usage of coordinator pattern.
/// It breaks the Coordinator abstraction and it has been introduced for Objective-C compatibility (mainly for integration in legacy view controllers).
/// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator.
@objcMembers
final class RoomNotificationSettingsCoordinatorBridgePresenter: NSObject {
// MARK: - Properties
// MARK: Private
private let room: MXRoom
private var coordinator: RoomNotificationSettingsCoordinator?
// MARK: Public
weak var delegate: RoomNotificationSettingsCoordinatorBridgePresenterDelegate?
// MARK: - Setup
init(room: MXRoom) {
self.room = room
super.init()
}
// MARK: - Public
// NOTE: Default value feature is not compatible with Objective-C.
// func present(from viewController: UIViewController, animated: Bool) {
// self.present(from: viewController, animated: animated)
// }
func present(from viewController: UIViewController, animated: Bool) {
let roomNotificationSettingsCoordinator = RoomNotificationSettingsCoordinator(room: room)
roomNotificationSettingsCoordinator.delegate = self
let presentable = roomNotificationSettingsCoordinator.toPresentable()
let navigationController = RiotNavigationController(rootViewController: presentable)
navigationController.modalPresentationStyle = .formSheet
presentable.presentationController?.delegate = self
viewController.present(navigationController, animated: animated, completion: nil)
roomNotificationSettingsCoordinator.start()
self.coordinator = roomNotificationSettingsCoordinator
}
func dismiss(animated: Bool, completion: (() -> Void)?) {
guard let coordinator = self.coordinator else {
return
}
coordinator.toPresentable().dismiss(animated: animated) {
self.coordinator = nil
if let completion = completion {
completion()
}
}
}
}
// MARK: - RoomNotificationSettingsCoordinatorDelegate
extension RoomNotificationSettingsCoordinatorBridgePresenter: RoomNotificationSettingsCoordinatorDelegate {
func roomNotificationSettingsCoordinatorDidCancel(_ coordinator: RoomNotificationSettingsCoordinatorType) {
self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self)
}
func roomNotificationSettingsCoordinatorDidComplete(_ coordinator: RoomNotificationSettingsCoordinatorType) {
self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self)
}
}
// MARK: - UIAdaptivePresentationControllerDelegate
extension RoomNotificationSettingsCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate {
func roomNotificationSettingsCoordinatorDidComplete(_ presentationController: UIPresentationController) {
self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self)
}
}
@@ -1,75 +0,0 @@
// File created from ScreenTemplate
// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings
/*
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 UIKit
final class RoomNotificationSettingsCoordinator: RoomNotificationSettingsCoordinatorType {
// MARK: - Properties
// MARK: Private
private var roomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType
private let roomNotificationSettingsViewController: RoomNotificationSettingsViewController
// MARK: Public
// Must be used only internally
var childCoordinators: [Coordinator] = []
weak var delegate: RoomNotificationSettingsCoordinatorDelegate?
// MARK: - Setup
init(room: MXRoom, showAvatar: Bool = true) {
let repository = RoomNotificationSettingsService(room: room)
let avatarData = showAvatar ? RoomAvatarViewData(
roomId: room.roomId,
displayName: room.summary.displayname,
avatarUrl: room.summary.avatar,
mediaManager: room.mxSession.mediaManager
) : nil
let roomNotificationSettingsViewModel = RoomNotificationSettingsViewModel(roomNotificationService: repository, roomEncrypted: room.summary.isEncrypted, avatarViewData: avatarData)
let roomNotificationSettingsViewController = RoomNotificationSettingsViewController.instantiate(with: roomNotificationSettingsViewModel)
self.roomNotificationSettingsViewModel = roomNotificationSettingsViewModel
self.roomNotificationSettingsViewController = roomNotificationSettingsViewController
}
// MARK: - Public methods
func start() {
self.roomNotificationSettingsViewModel.coordinatorDelegate = self
}
func toPresentable() -> UIViewController {
return self.roomNotificationSettingsViewController
}
}
// MARK: - RoomNotificationSettingsViewModelCoordinatorDelegate
extension RoomNotificationSettingsCoordinator: RoomNotificationSettingsViewModelCoordinatorDelegate {
func roomNotificationSettingsViewModelDidComplete(_ viewModel: RoomNotificationSettingsViewModelType) {
self.delegate?.roomNotificationSettingsCoordinatorDidComplete(self)
}
func roomNotificationSettingsViewModelDidCancel(_ viewModel: RoomNotificationSettingsViewModelType) {
self.delegate?.roomNotificationSettingsCoordinatorDidCancel(self)
}
}
@@ -1,29 +0,0 @@
// File created from ScreenTemplate
// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings
/*
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
protocol RoomNotificationSettingsCoordinatorDelegate: AnyObject {
func roomNotificationSettingsCoordinatorDidComplete(_ coordinator: RoomNotificationSettingsCoordinatorType)
func roomNotificationSettingsCoordinatorDidCancel(_ coordinator: RoomNotificationSettingsCoordinatorType)
}
/// `RoomNotificationSettingsCoordinatorType` is a protocol describing a Coordinator that handles changes to the room navigation settings navigation flow.
protocol RoomNotificationSettingsCoordinatorType: Coordinator, Presentable {
var delegate: RoomNotificationSettingsCoordinatorDelegate? { get }
}
@@ -1,27 +0,0 @@
//
// 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
typealias UpdateRoomNotificationStateCompletion = () -> Void
typealias RoomNotificationStateCallback = (RoomNotificationState) -> Void
protocol RoomNotificationSettingsServiceType {
func observeNotificationState(listener: @escaping RoomNotificationStateCallback)
func update(state: RoomNotificationState, completion: @escaping UpdateRoomNotificationStateCompletion)
var notificationState: RoomNotificationState { get }
}
@@ -1,26 +0,0 @@
// File created from ScreenTemplate
// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings
/*
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
/// RoomNotificationSettingsViewController view actions exposed to view model
enum RoomNotificationSettingsViewAction {
case load
case selectNotificationState(RoomNotificationState)
case save
case cancel
}
@@ -1,89 +0,0 @@
// File created from ScreenTemplate
// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings
/*
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
final class RoomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType {
// MARK: - Properties
// MARK: Private
private let roomNotificationService: RoomNotificationSettingsServiceType
private var state: RoomNotificationSettingsViewState {
willSet {
update(viewState: newValue)
}
}
// MARK: Public
weak var viewDelegate: RoomNotificationSettingsViewModelViewDelegate?
weak var coordinatorDelegate: RoomNotificationSettingsViewModelCoordinatorDelegate?
// MARK: - Setup
init(roomNotificationService: RoomNotificationSettingsServiceType, roomEncrypted: Bool, avatarViewData: AvatarViewDataProtocol?) {
self.roomNotificationService = roomNotificationService
let notificationState = Self.mapNotificationStateOnRead(encrypted: roomEncrypted, state: roomNotificationService.notificationState)
self.state = RoomNotificationSettingsViewState(roomEncrypted: roomEncrypted, saving: false, notificationState: notificationState, avatarData: avatarViewData)
self.roomNotificationService.observeNotificationState { [weak self] state in
guard let self = self else { return }
self.state.notificationState = Self.mapNotificationStateOnRead(encrypted: roomEncrypted, state: state)
}
}
// MARK: - Public
func process(viewAction: RoomNotificationSettingsViewAction) {
switch viewAction {
case .load:
update(viewState: self.state)
case .selectNotificationState(let state):
self.state.notificationState = state
case .save:
self.state.saving = true
roomNotificationService.update(state: state.notificationState) { [weak self] in
guard let self = self else { return }
self.state.saving = false
self.coordinatorDelegate?.roomNotificationSettingsViewModelDidComplete(self)
}
case .cancel:
coordinatorDelegate?.roomNotificationSettingsViewModelDidCancel(self)
}
}
// MARK: - Private
private static func mapNotificationStateOnRead(encrypted: Bool, state: RoomNotificationState) -> RoomNotificationState {
if encrypted, case .mentionsAndKeywordsOnly = state {
// Notifications not supported on encrypted rooms, map mentionsOnly to mute on read
return .mute
} else {
return state
}
}
private func update(viewState: RoomNotificationSettingsViewStateType) {
self.viewDelegate?.roomNotificationSettingsViewModel(self, didUpdateViewState: viewState)
}
}
@@ -1,37 +0,0 @@
// File created from ScreenTemplate
// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings
/*
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
protocol RoomNotificationSettingsViewModelViewDelegate: AnyObject {
func roomNotificationSettingsViewModel(_ viewModel: RoomNotificationSettingsViewModelType, didUpdateViewState viewState: RoomNotificationSettingsViewStateType)
}
protocol RoomNotificationSettingsViewModelCoordinatorDelegate: AnyObject {
func roomNotificationSettingsViewModelDidComplete(_ viewModel: RoomNotificationSettingsViewModelType)
func roomNotificationSettingsViewModelDidCancel(_ viewModel: RoomNotificationSettingsViewModelType)
}
/// Protocol describing the view model used by `RoomNotificationSettingsViewController`
protocol RoomNotificationSettingsViewModelType {
var viewDelegate: RoomNotificationSettingsViewModelViewDelegate? { get set }
var coordinatorDelegate: RoomNotificationSettingsViewModelCoordinatorDelegate? { get set }
func process(viewAction: RoomNotificationSettingsViewAction)
}
@@ -1,42 +0,0 @@
// File created from ScreenTemplate
// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings
/*
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
/// RoomNotificationSettingsViewController view state
struct RoomNotificationSettingsViewState: RoomNotificationSettingsViewStateType {
let roomEncrypted: Bool
var saving: Bool
var notificationState: RoomNotificationState
var notificationOptions: [RoomNotificationState] {
if roomEncrypted {
return [.all, .mute]
} else {
return RoomNotificationState.allCases
}
}
let avatarData: AvatarViewDataProtocol?
}
protocol RoomNotificationSettingsViewStateType {
var saving: Bool { get }
var roomEncrypted: Bool { get }
var notificationOptions: [RoomNotificationState] { get }
var notificationState: RoomNotificationState { get }
var avatarData: AvatarViewDataProtocol? { get }
}
@@ -1,23 +0,0 @@
//
// 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
enum RoomNotificationState: CaseIterable {
case all
case mentionsAndKeywordsOnly
case mute
}
@@ -1,331 +0,0 @@
//
// 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
final class RoomNotificationSettingsService: RoomNotificationSettingsServiceType {
typealias Completion = () -> Void
// MARK: - Properties
// MARK: Private
private let room: MXRoom
private var notificationCenterDidUpdateObserver: NSObjectProtocol?
private var notificationCenterDidFailObserver: NSObjectProtocol?
private var observers: [ObjectIdentifier] = []
// MARK: Public
var notificationState: RoomNotificationState {
room.notificationState
}
// MARK: - Setup
init(room: MXRoom) {
self.room = room
}
deinit {
observers.forEach(NotificationCenter.default.removeObserver)
}
// MARK: - Public
func observeNotificationState(listener: @escaping RoomNotificationStateCallback) {
let observer = NotificationCenter.default.addObserver(
forName: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules),
object: nil,
queue: OperationQueue.main) { [weak self] _ in
guard let self = self else { return }
listener(self.room.notificationState)
}
observers += [ObjectIdentifier(observer)]
}
func update(state: RoomNotificationState, completion: @escaping Completion) {
switch state {
case .all:
allMessages(completion: completion)
case .mentionsAndKeywordsOnly:
mentionsOnly(completion: completion)
case .mute:
mute(completion: completion)
}
}
// MARK: - Private
private func mute(completion: @escaping Completion) {
guard !room.isMuted else {
completion()
return
}
if let rule = room.roomPushRule {
removePushRule(rule: rule) {
self.mute(completion: completion)
}
return
}
guard let rule = room.overridePushRule else {
self.addPushRuleToMute(completion: completion)
return
}
guard notificationCenterDidUpdateObserver == nil else {
MXLog.debug("[RoomNotificationSettingsService] Request in progress: ignore push rule update")
completion()
return
}
// if the user defined one, use it
if rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify) {
enablePushRule(rule: rule, completion: completion)
} else {
removePushRule(rule: rule) {
self.addPushRuleToMute(completion: completion)
}
}
}
private func mentionsOnly(completion: @escaping Completion) {
guard !room.isMentionsOnly else {
completion()
return
}
if let rule = room.overridePushRule, room.isMuted {
removePushRule(rule: rule) {
self.mentionsOnly(completion: completion)
}
return
}
guard let rule = room.roomPushRule else {
addPushRuleToMentionOnly(completion: completion)
return
}
guard notificationCenterDidUpdateObserver == nil else {
MXLog.debug("[MXRoom+Riot] Request in progress: ignore push rule update")
completion()
return
}
// if the user defined one, use it
if rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify) {
enablePushRule(rule: rule, completion: completion)
} else {
removePushRule(rule: rule) {
self.addPushRuleToMentionOnly(completion: completion)
}
}
}
private func allMessages(completion: @escaping Completion) {
if !room.isMentionsOnly && !room.isMuted {
completion()
return
}
if let rule = room.overridePushRule, room.isMuted {
removePushRule(rule: rule) {
self.allMessages(completion: completion)
}
return
}
if let rule = room.roomPushRule, room.isMentionsOnly {
removePushRule(rule: rule, completion: completion)
}
}
private func addPushRuleToMentionOnly(completion: @escaping Completion) {
handleUpdateCallback(completion) { [weak self] in
guard let self = self else { return true }
return self.room.roomPushRule != nil
}
handleFailureCallback(completion)
room.mxSession.notificationCenter.addRoomRule(
room.roomId,
notify: false,
sound: false,
highlight: false)
}
private func addPushRuleToMute(completion: @escaping Completion) {
guard let roomId = room.roomId else {
return
}
handleUpdateCallback(completion) { [weak self] in
guard let self = self else { return true }
return self.room.overridePushRule != nil
}
handleFailureCallback(completion)
room.mxSession.notificationCenter.addOverrideRule(
withId: roomId,
conditions: [["kind": "event_match", "key": "room_id", "pattern": roomId]],
notify: false,
sound: false,
highlight: false
)
}
private func removePushRule(rule: MXPushRule, completion: @escaping Completion) {
handleUpdateCallback(completion) { [weak self] in
guard let self = self else { return true }
return self.room.mxSession.notificationCenter.rule(byId: rule.ruleId) == nil
}
handleFailureCallback(completion)
room.mxSession.notificationCenter.removeRule(rule)
}
private func enablePushRule(rule: MXPushRule, completion: @escaping Completion) {
handleUpdateCallback(completion) {
// No way to check whether this notification concerns the push rule. Consider the change is applied.
return true
}
handleFailureCallback(completion)
room.mxSession.notificationCenter.enableRule(rule, isEnabled: true)
}
private func handleUpdateCallback(_ completion: @escaping Completion, releaseCheck: @escaping () -> Bool) {
notificationCenterDidUpdateObserver = NotificationCenter.default.addObserver(
forName: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules),
object: nil,
queue: OperationQueue.main) { [weak self] _ in
guard let self = self else { return }
if releaseCheck() {
self.removeObservers()
completion()
}
}
}
private func handleFailureCallback(_ completion: @escaping Completion) {
notificationCenterDidFailObserver = NotificationCenter.default.addObserver(
forName: NSNotification.Name(rawValue: kMXNotificationCenterDidFailRulesUpdate),
object: nil,
queue: OperationQueue.main) { [weak self] _ in
guard let self = self else { return }
self.removeObservers()
completion()
}
}
func removeObservers() {
if let observer = self.notificationCenterDidUpdateObserver {
NotificationCenter.default.removeObserver(observer)
self.notificationCenterDidUpdateObserver = nil
}
if let observer = self.notificationCenterDidFailObserver {
NotificationCenter.default.removeObserver(observer)
self.notificationCenterDidFailObserver = nil
}
}
}
// We could move these to their own file and make available in global namespace or move to sdk but they are only used here at the moment
fileprivate extension MXRoom {
typealias Completion = () -> Void
func getRoomRule(from rules: [Any]) -> MXPushRule? {
guard let pushRules = rules as? [MXPushRule] else {
return nil
}
return pushRules.first(where: { self.roomId == $0.ruleId })
}
var overridePushRule: MXPushRule? {
guard let overrideRules = mxSession.notificationCenter.rules.global.override else {
return nil
}
return getRoomRule(from: overrideRules)
}
var roomPushRule: MXPushRule? {
guard let roomRules = mxSession.notificationCenter.rules.global.room else {
return nil
}
return getRoomRule(from: roomRules)
}
var notificationState: RoomNotificationState {
if isMuted {
return .mute
}
if isMentionsOnly {
return .mentionsAndKeywordsOnly
}
return .all
}
var isMuted: Bool {
// Check whether an override rule has been defined with the roomm id as rule id.
// This kind of rule is created to mute the room
guard let rule = self.overridePushRule,
rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify),
rule.conditionIsEnabled(kind: .eventMatch, for: roomId) else {
return false
}
return rule.enabled
}
var isMentionsOnly: Bool {
// Check push rules at room level
guard let rule = roomPushRule else { return false }
return rule.enabled && rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify)
}
}
fileprivate extension MXPushRule {
func actionsContains(actionType: MXPushRuleActionType) -> Bool {
guard let actions = actions as? [MXPushRuleAction] else {
return false
}
return actions.contains(where: { $0.actionType == actionType })
}
func conditionIsEnabled(kind: MXPushRuleConditionType, for roomId: String) -> Bool {
guard let conditions = conditions as? [MXPushRuleCondition] else {
return false
}
let ruleContainsCondition = conditions.contains { condition in
guard case kind = MXPushRuleConditionType(identifier: condition.kind),
let key = condition.parameters["key"] as? String,
let pattern = condition.parameters["pattern"] as? String
else { return false }
return key == "room_id" && pattern == roomId
}
return ruleContainsCondition && enabled
}
}
@@ -144,7 +144,7 @@ final class RoomNotificationSettingsViewController: UIViewController {
activityPresenter.removeCurrentActivityIndicator(animated: true)
}
self.viewState = viewState
if let avatarData = viewState.avatarData {
if let avatarData = viewState.avatarData as? AvatarViewDataProtocol {
mainTableView.tableHeaderView = avatarView
avatarView.configure(viewData: avatarData)
avatarView.update(theme: theme)
@@ -41,16 +41,3 @@ extension RoomNotificationSettingsCell: Themable {
selectedBackgroundView?.backgroundColor = theme.selectedBackgroundColor
}
}
fileprivate extension RoomNotificationState {
var title: String {
switch self {
case .all:
return VectorL10n.roomNotifsSettingsAllMessages
case .mentionsAndKeywordsOnly:
return VectorL10n.roomNotifsSettingsMentionsAndKeywords
case .mute:
return VectorL10n.roomNotifsSettingsNone
}
}
}