mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-17 23:18:27 +02:00
MESSENGER-4846 add federate toggle for room creation
This commit is contained in:
2
Podfile
2
Podfile
@@ -43,7 +43,7 @@ when String # specific MatrixSDK released version
|
||||
$matrixSDKVersionSpec = $matrixSDKVersion
|
||||
end
|
||||
|
||||
$matrixSDKVersionSpec = { :git => 'https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk', :tag => 'v2.12.0' }
|
||||
$matrixSDKVersionSpec = { :git => 'https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk', :tag => 'v2.13.0-RC01' }
|
||||
|
||||
# Method to import the MatrixSDK
|
||||
def import_MatrixSDK
|
||||
|
||||
@@ -414,6 +414,12 @@
|
||||
"user_avatar_view_accessibility_label" = "Profilbild";
|
||||
"secrets_recovery_with_key_information_unlock_secure_backup_with_phrase" = "Zum Forfahren gib deinen Wiederherstellungsschlüssel ein.";
|
||||
|
||||
"create_room_type_federated" = "Für eine Föderation zulassen";
|
||||
"create_room_type_federated_subtext" = "(Raum kann von externen Organisationen mitgenutzt werden)";
|
||||
"create_room_deactivate_federation_for_room_error_title" = "Föderation aktiv";
|
||||
"create_room_deactivate_federation_for_room_error_text" = "Die Föderation konnte nicht deaktiviert werden, bitte versuche es später erneut.";
|
||||
"create_room_deactivate_federation_alert_dismiss_button" = "Ok";
|
||||
|
||||
// Mark: - Voice Messages
|
||||
|
||||
"voice_message_release_to_send" = "Zur Aufnahme halten, zum Senden loslassen";
|
||||
|
||||
@@ -326,6 +326,12 @@
|
||||
// Mark: - Room Creation
|
||||
|
||||
"room_intro_cell_information_dm_sentence1_part1" = "This is the beginning of your direct message history with ";
|
||||
"create_room_type_federated" = "Allow federation";
|
||||
"create_room_type_federated_subtext" = "(External organizations can join the room)";
|
||||
"create_room_deactivate_federation_for_room_error_title" = "Federation active";
|
||||
"create_room_deactivate_federation_for_room_error_text" = "The federation could not be disabled, please try again later.";
|
||||
"create_room_deactivate_federation_alert_dismiss_button" = "Ok";
|
||||
|
||||
|
||||
// MARK: - Notification Times
|
||||
|
||||
|
||||
@@ -719,10 +719,30 @@ public class BWIL10n: NSObject {
|
||||
public static var create: String {
|
||||
return BWIL10n.tr("Bwi", "create")
|
||||
}
|
||||
/// Ok
|
||||
public static var createRoomDeactivateFederationAlertDismissButton: String {
|
||||
return BWIL10n.tr("Bwi", "create_room_deactivate_federation_alert_dismiss_button")
|
||||
}
|
||||
/// Die Föderation konnte nicht deaktiviert werden, bitte versuche es später erneut.
|
||||
public static var createRoomDeactivateFederationForRoomErrorText: String {
|
||||
return BWIL10n.tr("Bwi", "create_room_deactivate_federation_for_room_error_text")
|
||||
}
|
||||
/// Föderation aktiv
|
||||
public static var createRoomDeactivateFederationForRoomErrorTitle: String {
|
||||
return BWIL10n.tr("Bwi", "create_room_deactivate_federation_for_room_error_title")
|
||||
}
|
||||
/// Thema
|
||||
public static var createRoomPlaceholderTopic: String {
|
||||
return BWIL10n.tr("Bwi", "create_room_placeholder_topic")
|
||||
}
|
||||
/// Für eine Föderation zulassen
|
||||
public static var createRoomTypeFederated: String {
|
||||
return BWIL10n.tr("Bwi", "create_room_type_federated")
|
||||
}
|
||||
/// (Raum kann von externen Organisationen mitgenutzt werden)
|
||||
public static var createRoomTypeFederatedSubtext: String {
|
||||
return BWIL10n.tr("Bwi", "create_room_type_federated_subtext")
|
||||
}
|
||||
/// Verifizierung abgebrochen. Du kannst sie erneut starten.
|
||||
public static var deviceVerificationCancelled: String {
|
||||
return BWIL10n.tr("Bwi", "device_verification_cancelled")
|
||||
|
||||
@@ -22,6 +22,7 @@ import UIKit
|
||||
enum EnterNewRoomDetailsViewAction {
|
||||
case loadData
|
||||
case chooseAvatar(sourceView: UIView)
|
||||
case updateServerACLRule // bwi: #4846
|
||||
case removeAvatar
|
||||
case cancel
|
||||
case create
|
||||
|
||||
@@ -35,6 +35,7 @@ final class EnterNewRoomDetailsViewController: UIViewController {
|
||||
static let roomTopicMaximumNumberOfChars = 250
|
||||
static let chooseAvatarTableViewCellHeight: CGFloat = 140
|
||||
static let textViewTableViewCellHeight: CGFloat = 150
|
||||
static let bwiToggleWithLabelAndSubLabelCellReuseIdentifier = "bwiToggleWithLabelAndSubLabelCellReuseIdentifier" // bwi: #4846
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
@@ -74,11 +75,13 @@ final class EnterNewRoomDetailsViewController: UIViewController {
|
||||
case textField(tag: Int, placeholder: String?, delegate: UITextFieldDelegate?)
|
||||
case textView(tag: Int, placeholder: String?, delegate: UITextViewDelegate?)
|
||||
case withSwitch(isOn: Bool, onValueChanged: ((UISwitch) -> Void)?)
|
||||
case withSwitchWithSubText(onValueChanged: ((Bool) -> Void)?) // bwi: #4846
|
||||
}
|
||||
|
||||
private struct Row {
|
||||
var type: RowType
|
||||
var text: String?
|
||||
var subText: String? // bwi: #4846
|
||||
var accessoryType: UITableViewCell.AccessoryType = .none
|
||||
var action: (() -> Void)?
|
||||
}
|
||||
@@ -169,12 +172,24 @@ final class EnterNewRoomDetailsViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
}
|
||||
// bwi: #4846 add serverACLRule on roomcreation
|
||||
let row_4_3 = Row(type: .withSwitchWithSubText(onValueChanged: { [weak self] newToggleValue in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
viewModel.process(viewAction: .updateServerACLRule)
|
||||
}), text: BWIL10n.createRoomTypeFederated, subText: BWIL10n.createRoomTypeFederatedSubtext)
|
||||
let rows: [Row]
|
||||
switch viewModel.actionType {
|
||||
case .createAndAddToSpace:
|
||||
rows = [row_4_0, row_4_1, row_4_2]
|
||||
case .createOnly:
|
||||
rows = [row_4_0, row_4_2]
|
||||
// bwi: #4846 add serverACLRule on roomcreation
|
||||
if BWIBuildSettings.shared.isFederationEnabled {
|
||||
rows = [row_4_0, row_4_2, row_4_3]
|
||||
} else {
|
||||
rows = [row_4_0, row_4_2]
|
||||
}
|
||||
}
|
||||
var footer: String
|
||||
switch viewModel.roomCreationParameters.joinRule {
|
||||
@@ -348,6 +363,8 @@ final class EnterNewRoomDetailsViewController: UIViewController {
|
||||
mainTableView.register(cellType: TextFieldTableViewCell.self)
|
||||
mainTableView.register(cellType: TextViewTableViewCell.self)
|
||||
mainTableView.register(headerFooterViewType: TextViewTableViewHeaderFooterView.self)
|
||||
// bwi: #4846 add serverACLRule on roomcreation
|
||||
mainTableView.register(TableViewCellWithLabelSubLabelAndSwitch<TableViewCellWithLabelSubLabelAndSwitchView>.self, forCellReuseIdentifier: Constants.bwiToggleWithLabelAndSubLabelCellReuseIdentifier)
|
||||
mainTableView.sectionHeaderHeight = UITableView.automaticDimension
|
||||
mainTableView.estimatedSectionHeaderHeight = 50
|
||||
mainTableView.sectionFooterHeight = UITableView.automaticDimension
|
||||
@@ -490,6 +507,22 @@ extension EnterNewRoomDetailsViewController: UITableViewDataSource {
|
||||
cell.mxkSwitchTrailingConstraint.constant = 15
|
||||
cell.update(theme: theme)
|
||||
|
||||
return cell
|
||||
|
||||
// bwi: #4846 add toggle with subtext for federation
|
||||
case .withSwitchWithSubText(let onValueChanged):
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: Constants.bwiToggleWithLabelAndSubLabelCellReuseIdentifier, for: indexPath) as? TableViewCellWithLabelSubLabelAndSwitch<TableViewCellWithLabelSubLabelAndSwitchView> else {
|
||||
return UITableViewCell()
|
||||
}
|
||||
cell.selectionStyle = .none
|
||||
if let viewModel = viewModel as? EnterNewRoomDetailsViewModel {
|
||||
cell.setupView(parent: self, rootView: TableViewCellWithLabelSubLabelAndSwitchView(viewModel: viewModel, toggleText: row.text ?? "", subText: row.subText ?? "", onValueChanged: { newToggleValue in
|
||||
onValueChanged?(newToggleValue)
|
||||
}))
|
||||
} else {
|
||||
return UITableViewCell()
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
@@ -600,6 +633,20 @@ extension EnterNewRoomDetailsViewController: EnterNewRoomDetailsViewModelViewDel
|
||||
func enterNewRoomDetailsViewModel(_ viewModel: EnterNewRoomDetailsViewModelType, didUpdateViewState viewSate: EnterNewRoomDetailsViewState) {
|
||||
self.render(viewState: viewSate)
|
||||
}
|
||||
|
||||
// bwi: #4846 add serverACLRule on roomcreation
|
||||
func showDeactivateFederationForRoomErrorAlert() {
|
||||
let alert = UIAlertController(title: BWIL10n.createRoomDeactivateFederationForRoomErrorTitle,
|
||||
message: BWIL10n.createRoomDeactivateFederationForRoomErrorText,
|
||||
preferredStyle: .alert)
|
||||
|
||||
let closeAction = UIAlertAction(title: BWIL10n.createRoomDeactivateFederationAlertDismissButton, style: .default, handler: { _ in
|
||||
})
|
||||
|
||||
alert.addAction(closeAction)
|
||||
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UITextFieldDelegate
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType {
|
||||
final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType, ObservableObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
@@ -36,6 +36,9 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType {
|
||||
weak var coordinatorDelegate: EnterNewRoomDetailsViewModelCoordinatorDelegate?
|
||||
var roomCreationParameters: RoomCreationParameters = RoomCreationParameters()
|
||||
|
||||
// bwi: #4846 add serverACLRule on roomcreation
|
||||
@Published var serverACLToggleValue: Bool = false
|
||||
|
||||
private(set) var viewState: EnterNewRoomDetailsViewState {
|
||||
didSet {
|
||||
self.viewDelegate?.enterNewRoomDetailsViewModel(self, didUpdateViewState: viewState)
|
||||
@@ -54,6 +57,11 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType {
|
||||
roomCreationParameters.isEncrypted = session.vc_homeserverConfiguration().encryption.isE2EEByDefaultEnabled && RiotSettings.shared.roomCreationScreenRoomIsEncrypted
|
||||
roomCreationParameters.joinRule = RiotSettings.shared.roomCreationScreenRoomIsPublic ? .public : .private
|
||||
viewState = .loaded
|
||||
|
||||
// bwi: #4846 add serverACLRule on roomcreation
|
||||
if BWIBuildSettings.shared.isFederationEnabled {
|
||||
updateServerACLRule()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
@@ -75,6 +83,9 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType {
|
||||
self.coordinatorDelegate?.enterNewRoomDetailsViewModelDidCancel(self)
|
||||
case .create:
|
||||
self.createRoom()
|
||||
// bwi: #4846 add serverACLRule on roomcreation
|
||||
case .updateServerACLRule:
|
||||
self.updateServerACLRule()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +140,7 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType {
|
||||
parentRoomId: parentSpace?.spaceId,
|
||||
aliasLocalPart: fixRoomAlias(alias: roomCreationParameters.address),
|
||||
isEncrypted: roomCreationParameters.isEncrypted,
|
||||
serverACLRule: roomCreationParameters.serverACLRule,
|
||||
completion: { response in
|
||||
switch response {
|
||||
case .success(let room):
|
||||
@@ -203,6 +215,25 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bwi: #4846 add serverACLRule on roomcreation
|
||||
private func updateServerACLRule() {
|
||||
var allowedServers = [String]()
|
||||
if serverACLToggleValue {
|
||||
// Room is federated, allow other user from other servers to join the room
|
||||
allowedServers.append("*")
|
||||
} else {
|
||||
if let host = URLComponents(string: "something")?.host {
|
||||
// Room is not federated, only user from the same homeserver can join the room
|
||||
allowedServers.append(host)
|
||||
} else {
|
||||
serverACLToggleValue = true
|
||||
self.viewDelegate?.showDeactivateFederationForRoomErrorAlert()
|
||||
}
|
||||
}
|
||||
|
||||
roomCreationParameters.serverACLRule = MXRoomServerACLRule(allow: allowedServers)
|
||||
}
|
||||
|
||||
private func cancelOperations() {
|
||||
self.currentOperation?.cancel()
|
||||
|
||||
@@ -20,6 +20,7 @@ import Foundation
|
||||
|
||||
protocol EnterNewRoomDetailsViewModelViewDelegate: AnyObject {
|
||||
func enterNewRoomDetailsViewModel(_ viewModel: EnterNewRoomDetailsViewModelType, didUpdateViewState viewSate: EnterNewRoomDetailsViewState)
|
||||
func showDeactivateFederationForRoomErrorAlert() // bwi: #4846
|
||||
}
|
||||
|
||||
protocol EnterNewRoomDetailsViewModelCoordinatorDelegate: AnyObject {
|
||||
|
||||
@@ -38,6 +38,7 @@ struct RoomCreationParameters {
|
||||
}
|
||||
}
|
||||
}
|
||||
var serverACLRule: MXRoomServerACLRule? // bwi: #4846
|
||||
var showInDirectory: Bool = false
|
||||
var isRoomSuggested: Bool = false
|
||||
|
||||
|
||||
113
bwi/CommonUI/TableViewCellWithLabelSubLabelAndSwitch.swift
Normal file
113
bwi/CommonUI/TableViewCellWithLabelSubLabelAndSwitch.swift
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
/*
|
||||
* Copyright (c) 2023 BWI GmbH
|
||||
*
|
||||
* 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 SwiftUI
|
||||
import Foundation
|
||||
|
||||
/// Helper class for making our SwiftUI view available to ObjectiveC
|
||||
@objcMembers class TableViewCellWithLabelSubLabelAndSwitch<Content: View>: MXKTableViewCell {
|
||||
private var parentViewController: UIViewController?
|
||||
private let hostingController = UIHostingController<Content?>(rootView: nil)
|
||||
|
||||
private var theme: Theme!
|
||||
|
||||
override init!(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func setupView(parent: UIViewController, rootView: Content) {
|
||||
self.parentViewController = parent
|
||||
hostingController.rootView = rootView
|
||||
|
||||
let shouldControllerMove = hostingController.parent != parent
|
||||
if shouldControllerMove {
|
||||
removeController()
|
||||
parent.addChild(hostingController)
|
||||
}
|
||||
|
||||
if !self.contentView.subviews.contains(hostingController.view) {
|
||||
self.contentView.addSubview(hostingController.view)
|
||||
self.contentView.vc_addSubViewMatchingParentSafeArea(hostingController.view)
|
||||
}
|
||||
|
||||
if shouldControllerMove {
|
||||
hostingController.didMove(toParent: parent)
|
||||
}
|
||||
|
||||
registerThemeServiceDidChangeThemeNotification()
|
||||
update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
|
||||
@objc private func themeDidChange() {
|
||||
update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
|
||||
private func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
hostingController.view.backgroundColor = theme.headerBackgroundColor
|
||||
}
|
||||
|
||||
deinit {
|
||||
removeController()
|
||||
}
|
||||
|
||||
private func removeController() {
|
||||
hostingController.willMove(toParent: nil)
|
||||
hostingController.view.removeFromSuperview()
|
||||
hostingController.removeFromParent()
|
||||
parentViewController = nil
|
||||
}
|
||||
}
|
||||
|
||||
struct TableViewCellWithLabelSubLabelAndSwitchView: View {
|
||||
@ObservedObject var viewModel: EnterNewRoomDetailsViewModel
|
||||
var toggleText: String
|
||||
var subText: String
|
||||
@Environment(\.theme) private var theme
|
||||
|
||||
var onValueChanged: ((_: Bool) -> Void)?
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Toggle(isOn: $viewModel.serverACLToggleValue) {
|
||||
Text(toggleText)
|
||||
.lineLimit(nil)
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: Color(ThemeService.shared().theme.tintColor)))
|
||||
.onChange(of: viewModel.serverACLToggleValue) { newToggleValue in
|
||||
onValueChanged?(newToggleValue)
|
||||
}
|
||||
}
|
||||
Text(subText)
|
||||
.font(.system(size: 15))
|
||||
.foregroundColor(theme.colors.secondaryContent)
|
||||
.lineLimit(nil)
|
||||
}
|
||||
.padding([.leading, .trailing], 16)
|
||||
.padding([.top, .bottom], 8)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user