mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-16 06:28:27 +02:00
Merge pull request #6590 from vector-im/gil/6574-App_Layout_Context_Menus
Update app layout context menus
This commit is contained in:
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "home_my_spaces_action.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true,
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.75" y="0.75" width="7.5" height="7.5" rx="1.25" stroke="#0DBD8B" stroke-width="1.5"/>
|
||||
<rect x="0.75" y="11.8613" width="7.5" height="7.5" rx="1.25" stroke="#0DBD8B" stroke-width="1.5"/>
|
||||
<rect x="11.1111" width="9" height="9" rx="2" fill="#0DBD8B"/>
|
||||
<rect x="11.8611" y="11.8613" width="7.5" height="7.5" rx="1.25" stroke="#0DBD8B" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 466 B |
@@ -77,6 +77,7 @@
|
||||
"suggest" = "Suggest";
|
||||
"edit" = "Edit";
|
||||
"confirm" = "Confirm";
|
||||
"invite_to" = "Invite to %@";
|
||||
|
||||
// Activities
|
||||
"loading" = "Loading";
|
||||
@@ -2006,6 +2007,7 @@ Tap the + to start adding people.";
|
||||
"leave_space_only_action" = "Don't leave any rooms";
|
||||
"leave_space_and_all_rooms_action" = "Leave all rooms and spaces";
|
||||
"spaces_explore_rooms" = "Explore rooms";
|
||||
"spaces_explore_rooms_format" = "Explore %@";
|
||||
"spaces_suggested_room" = "Suggested";
|
||||
"spaces_explore_rooms_room_number" = "%@ rooms";
|
||||
"spaces_explore_rooms_one_room" = "1 room";
|
||||
|
||||
@@ -115,7 +115,6 @@ internal class Asset: NSObject {
|
||||
internal static let roomActionPriorityLow = ImageAsset(name: "room_action_priority_low")
|
||||
internal static let homeEmptyScreenArtwork = ImageAsset(name: "home_empty_screen_artwork")
|
||||
internal static let homeEmptyScreenArtworkDark = ImageAsset(name: "home_empty_screen_artwork_dark")
|
||||
internal static let homeMySpacesAction = ImageAsset(name: "home_my_spaces_action")
|
||||
internal static let plusFloatingAction = ImageAsset(name: "plus_floating_action")
|
||||
internal static let versionCheckCloseIcon = ImageAsset(name: "version_check_close_icon")
|
||||
internal static let versionCheckInfoIcon = ImageAsset(name: "version_check_info_icon")
|
||||
|
||||
@@ -2491,6 +2491,10 @@ public class VectorL10n: NSObject {
|
||||
public static func inviteFriendsShareText(_ p1: String, _ p2: String) -> String {
|
||||
return VectorL10n.tr("Vector", "invite_friends_share_text", p1, p2)
|
||||
}
|
||||
/// Invite to %@
|
||||
public static func inviteTo(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "invite_to", p1)
|
||||
}
|
||||
/// Invite matrix User
|
||||
public static var inviteUser: String {
|
||||
return VectorL10n.tr("Vector", "invite_user")
|
||||
@@ -8047,6 +8051,10 @@ public class VectorL10n: NSObject {
|
||||
public static var spacesExploreRooms: String {
|
||||
return VectorL10n.tr("Vector", "spaces_explore_rooms")
|
||||
}
|
||||
/// Explore %@
|
||||
public static func spacesExploreRoomsFormat(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "spaces_explore_rooms_format", p1)
|
||||
}
|
||||
/// 1 room
|
||||
public static var spacesExploreRoomsOneRoom: String {
|
||||
return VectorL10n.tr("Vector", "spaces_explore_rooms_one_room")
|
||||
|
||||
@@ -28,7 +28,7 @@ class AllChatsActionProvider {
|
||||
// MARK: - RoomActionProviderProtocol
|
||||
|
||||
var menu: UIMenu {
|
||||
return UIMenu(title: VectorL10n.allChatsEditLayout, children: [
|
||||
return UIMenu(title: "", children: [
|
||||
self.recentsAction,
|
||||
self.filtersAction,
|
||||
UIMenu(title: "", options: .displayInline, children: [
|
||||
|
||||
@@ -21,10 +21,6 @@ enum AllChatsEditActionProviderOption {
|
||||
case exploreRooms
|
||||
case createRoom
|
||||
case startChat
|
||||
case invitePeople
|
||||
case spaceMembers
|
||||
case spaceSettings
|
||||
case leaveSpace
|
||||
case createSpace
|
||||
}
|
||||
|
||||
@@ -56,30 +52,26 @@ class AllChatsEditActionProvider {
|
||||
var menu: UIMenu {
|
||||
guard parentSpace != nil else {
|
||||
var createActions = [
|
||||
self.startChatAction,
|
||||
self.createRoomAction
|
||||
self.createRoomAction,
|
||||
self.startChatAction
|
||||
]
|
||||
if rootSpaceCount > 0 {
|
||||
createActions.append(self.createSpaceAction)
|
||||
createActions.insert(self.createSpaceAction, at: 0)
|
||||
}
|
||||
return UIMenu(title: VectorL10n.allChatsTitle, children: [
|
||||
return UIMenu(title: "", children: [
|
||||
self.exploreRoomsAction,
|
||||
UIMenu(title: "", options: .displayInline, children: createActions)
|
||||
])
|
||||
}
|
||||
|
||||
return UIMenu(title: parentName, children: [
|
||||
return UIMenu(title: "", children: [
|
||||
UIMenu(title: "", options: .displayInline, children: [
|
||||
self.spaceMembersAction,
|
||||
self.exploreRoomsAction,
|
||||
self.spaceSettingsAction
|
||||
self.exploreRoomsAction
|
||||
]),
|
||||
UIMenu(title: "", options: .displayInline, children: [
|
||||
self.invitePeopleAction,
|
||||
self.createRoomAction,
|
||||
self.createSpaceAction
|
||||
]),
|
||||
self.leaveSpaceAction
|
||||
self.createSpaceAction,
|
||||
self.createRoomAction
|
||||
])
|
||||
])
|
||||
}
|
||||
|
||||
@@ -139,8 +131,8 @@ class AllChatsEditActionProvider {
|
||||
// MARK: - Private
|
||||
|
||||
private var exploreRoomsAction: UIAction {
|
||||
UIAction(title: VectorL10n.spacesExploreRooms,
|
||||
image: parentSpace == nil ? UIImage(systemName: "list.bullet") : UIImage(systemName: "square.fill.text.grid.1x2")) { [weak self] action in
|
||||
UIAction(title: parentSpace == nil ? VectorL10n.spacesExploreRooms : VectorL10n.spacesExploreRoomsFormat(parentName),
|
||||
image: UIImage(systemName: "list.bullet")) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsEditActionProvider(self, didSelect: .exploreRooms)
|
||||
@@ -175,42 +167,4 @@ class AllChatsEditActionProvider {
|
||||
self.delegate?.allChatsEditActionProvider(self, didSelect: .createSpace)
|
||||
}
|
||||
}
|
||||
|
||||
private var invitePeopleAction: UIAction {
|
||||
UIAction(title: VectorL10n.spacesInvitePeople,
|
||||
image: UIImage(systemName: "person.badge.plus"),
|
||||
attributes: isInviteAvailable ? [] : .disabled) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsEditActionProvider(self, didSelect: .invitePeople)
|
||||
}
|
||||
}
|
||||
|
||||
private var spaceMembersAction: UIAction {
|
||||
UIAction(title: VectorL10n.roomDetailsPeople,
|
||||
image: UIImage(systemName: "person.3")) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsEditActionProvider(self, didSelect: .spaceMembers)
|
||||
}
|
||||
}
|
||||
|
||||
private var spaceSettingsAction: UIAction {
|
||||
UIAction(title: VectorL10n.allChatsEditMenuSpaceSettings,
|
||||
image: UIImage(systemName: "gearshape")) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsEditActionProvider(self, didSelect: .spaceSettings)
|
||||
}
|
||||
}
|
||||
|
||||
private var leaveSpaceAction: UIAction {
|
||||
UIAction(title: VectorL10n.allChatsEditMenuLeaveSpace(parentName),
|
||||
image: UIImage(systemName: "rectangle.portrait.and.arrow.right.fill"),
|
||||
attributes: .destructive) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsEditActionProvider(self, didSelect: .leaveSpace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
//
|
||||
// Copyright 2022 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
|
||||
import MatrixSDK
|
||||
|
||||
enum AllChatsSpaceActionProviderOption {
|
||||
case invitePeople
|
||||
case spaceMembers
|
||||
case spaceSettings
|
||||
case leaveSpace
|
||||
}
|
||||
|
||||
protocol AllChatsSpaceActionProviderDelegate: AnyObject {
|
||||
func allChatsSpaceActionProvider(_ actionProvider: AllChatsSpaceActionProvider, didSelect option: AllChatsSpaceActionProviderOption)
|
||||
}
|
||||
|
||||
/// `AllChatsSpaceActionProvider` provides the menu for accessing space options according to the current space
|
||||
class AllChatsSpaceActionProvider {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
weak var delegate: AllChatsSpaceActionProviderDelegate?
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private var currentSpace: MXSpace? {
|
||||
didSet {
|
||||
spaceName = currentSpace?.summary?.displayname ?? VectorL10n.spaceTag
|
||||
}
|
||||
}
|
||||
private var spaceName: String = VectorL10n.spaceTag
|
||||
private var isInviteAvailable: Bool = false
|
||||
|
||||
// MARK: - RoomActionProviderProtocol
|
||||
|
||||
var menu: UIMenu {
|
||||
guard currentSpace != nil else {
|
||||
return UIMenu(title: "", children: [])
|
||||
}
|
||||
|
||||
return UIMenu(title: "", children: [
|
||||
UIMenu(title: "", options: .displayInline, children: [
|
||||
self.spaceSettingsAction,
|
||||
self.spaceMembersAction,
|
||||
self.invitePeopleAction
|
||||
]),
|
||||
self.leaveSpaceAction
|
||||
])
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
/// Returns an instance of the updated menu accordingly to the given parameters.
|
||||
///
|
||||
/// Some menu items can be disabled depending on the required power levels of the `parentSpace`. Therefore, `updateMenu()` first returns a temporary context menu
|
||||
/// with all sensible items disabled, asynchronously fetches power levels of the `parentSpace`, then gives a new instance of the menu with, potentially, all sensible items
|
||||
/// enabled via the `completion` callback.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - session: The current `MXSession` instance
|
||||
/// - space: The current space (`nil` for home space)
|
||||
/// - completion: callback called once the power levels of the `parentSpace` have been fetched and the menu items have been computed accordingly.
|
||||
/// - Returns: If the `parentSpace` is `nil`, the context menu, the temporary context menu otherwise.
|
||||
func updateMenu(with session: MXSession?, space: MXSpace?, completion: @escaping (UIMenu) -> Void) -> UIMenu {
|
||||
self.currentSpace = space
|
||||
isInviteAvailable = false
|
||||
|
||||
guard let currentSpace = currentSpace, let spaceRoom = currentSpace.room, let session = session else {
|
||||
return self.menu
|
||||
}
|
||||
|
||||
spaceRoom.state { [weak self] roomState in
|
||||
guard let self = self else { return }
|
||||
|
||||
guard let powerLevels = roomState?.powerLevels, let userId = session.myUserId else {
|
||||
return
|
||||
}
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: userId)
|
||||
|
||||
self.isInviteAvailable = userPowerLevel >= powerLevels.invite
|
||||
|
||||
completion(self.menu)
|
||||
}
|
||||
|
||||
return self.menu
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private var invitePeopleAction: UIAction {
|
||||
UIAction(title: VectorL10n.inviteTo(spaceName),
|
||||
image: UIImage(systemName: "square.and.arrow.up"),
|
||||
attributes: isInviteAvailable ? [] : .disabled) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsSpaceActionProvider(self, didSelect: .invitePeople)
|
||||
}
|
||||
}
|
||||
|
||||
private var spaceMembersAction: UIAction {
|
||||
UIAction(title: VectorL10n.roomDetailsPeople,
|
||||
image: UIImage(systemName: "person")) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsSpaceActionProvider(self, didSelect: .spaceMembers)
|
||||
}
|
||||
}
|
||||
|
||||
private var spaceSettingsAction: UIAction {
|
||||
UIAction(title: VectorL10n.allChatsEditMenuSpaceSettings,
|
||||
image: UIImage(systemName: "gearshape")) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsSpaceActionProvider(self, didSelect: .spaceSettings)
|
||||
}
|
||||
}
|
||||
|
||||
private var leaveSpaceAction: UIAction {
|
||||
UIAction(title: VectorL10n.allChatsEditMenuLeaveSpace(spaceName),
|
||||
image: UIImage(systemName: "rectangle.portrait.and.arrow.right.fill"),
|
||||
attributes: .destructive) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.allChatsSpaceActionProvider(self, didSelect: .leaveSpace)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,8 @@ class AllChatsViewController: HomeViewController {
|
||||
|
||||
private let searchController = UISearchController(searchResultsController: nil)
|
||||
|
||||
private let spaceActionProvider = AllChatsSpaceActionProvider()
|
||||
|
||||
private let editActionProvider = AllChatsEditActionProvider()
|
||||
|
||||
private var spaceSelectorBridgePresenter: SpaceSelectorBottomSheetCoordinatorBridgePresenter?
|
||||
@@ -49,6 +51,7 @@ class AllChatsViewController: HomeViewController {
|
||||
super.viewDidLoad()
|
||||
|
||||
editActionProvider.delegate = self
|
||||
spaceActionProvider.delegate = self
|
||||
|
||||
recentsTableView.tag = RecentsDataSourceMode.allChats.rawValue
|
||||
recentsTableView.clipsToBounds = false
|
||||
@@ -59,7 +62,6 @@ class AllChatsViewController: HomeViewController {
|
||||
searchController.obscuresBackgroundDuringPresentation = false
|
||||
searchController.searchResultsUpdater = self
|
||||
|
||||
self.setupEditOptions()
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.setupEditOptions), name: AllChatsLayoutSettingsManager.didUpdateSettings, object: nil)
|
||||
}
|
||||
|
||||
@@ -171,26 +173,37 @@ class AllChatsViewController: HomeViewController {
|
||||
// MARK: - Private
|
||||
|
||||
@objc private func setupEditOptions() {
|
||||
self.tabBarController?.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "line.3.horizontal.decrease.circle"), menu: AllChatsActionProvider().menu)
|
||||
guard let currentSpace = self.dataSource?.currentSpace else {
|
||||
updateRightNavigationItem(with: AllChatsActionProvider().menu)
|
||||
return
|
||||
}
|
||||
|
||||
updateRightNavigationItem(with: spaceActionProvider.updateMenu(with: mainSession, space: currentSpace) { [weak self] menu in
|
||||
self?.updateRightNavigationItem(with: menu)
|
||||
})
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
let currentSpace = self.dataSource?.currentSpace
|
||||
self.tabBarController?.title = currentSpace?.summary?.displayname ?? VectorL10n.allChatsTitle
|
||||
|
||||
setupEditOptions()
|
||||
updateToolbar(with: editActionProvider.updateMenu(with: mainSession, parentSpace: currentSpace, completion: { [weak self] menu in
|
||||
self?.updateToolbar(with: menu)
|
||||
}))
|
||||
}
|
||||
|
||||
private func updateRightNavigationItem(with menu: UIMenu) {
|
||||
self.tabBarController?.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "ellipsis.circle"), menu: menu)
|
||||
}
|
||||
|
||||
private func updateToolbar(with menu: UIMenu) {
|
||||
let currentSpace = self.dataSource?.currentSpace
|
||||
self.navigationController?.isToolbarHidden = false
|
||||
self.update(with: ThemeService.shared().theme)
|
||||
self.tabBarController?.setToolbarItems([
|
||||
UIBarButtonItem(image: Asset.Images.homeMySpacesAction.image, style: .done, target: self, action: #selector(self.showSpaceSelectorAction(sender: ))),
|
||||
UIBarButtonItem(image: UIImage(systemName: "square.grid.2x2"), style: .done, target: self, action: #selector(self.showSpaceSelectorAction(sender: ))),
|
||||
UIBarButtonItem.flexibleSpace(),
|
||||
UIBarButtonItem(image: UIImage(systemName: currentSpace == nil ? "square.and.pencil" : "ellipsis.circle"), menu: menu)
|
||||
UIBarButtonItem(image: UIImage(systemName: "square.and.pencil"), menu: menu)
|
||||
], animated: true)
|
||||
}
|
||||
|
||||
@@ -395,6 +408,17 @@ extension AllChatsViewController: AllChatsEditActionProviderDelegate {
|
||||
createNewRoom()
|
||||
case .startChat:
|
||||
startChat()
|
||||
case .createSpace:
|
||||
showCreateSpace(parentSpaceId: dataSource.currentSpace?.spaceId)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - AllChatsSpaceActionProviderDelegate
|
||||
extension AllChatsViewController: AllChatsSpaceActionProviderDelegate {
|
||||
func allChatsSpaceActionProvider(_ actionProvider: AllChatsSpaceActionProvider, didSelect option: AllChatsSpaceActionProviderOption) {
|
||||
switch option {
|
||||
case .invitePeople:
|
||||
showSpaceInvite()
|
||||
case .spaceMembers:
|
||||
@@ -403,11 +427,8 @@ extension AllChatsViewController: AllChatsEditActionProviderDelegate {
|
||||
showSpaceSettings()
|
||||
case .leaveSpace:
|
||||
showLeaveSpace()
|
||||
case .createSpace:
|
||||
showCreateSpace(parentSpaceId: dataSource.currentSpace?.spaceId)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - ContactsPickerCoordinatorDelegate
|
||||
|
||||
@@ -743,13 +743,13 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
|
||||
private func createAvatarButtonItem(for viewController: UIViewController) {
|
||||
var actions: [UIMenuElement] = []
|
||||
|
||||
actions.append(UIAction(title: VectorL10n.allChatsUserMenuSettings, image: UIImage(systemName: "gearshape")) { [weak self] action in
|
||||
actions.append(UIAction(title: VectorL10n.settings, image: UIImage(systemName: "gearshape")) { [weak self] action in
|
||||
self?.showSettings()
|
||||
})
|
||||
|
||||
var subMenuActions: [UIAction] = []
|
||||
if BuildSettings.sideMenuShowInviteFriends {
|
||||
subMenuActions.append(UIAction(title: VectorL10n.sideMenuActionInviteFriends, image: UIImage(systemName: "square.and.arrow.up.fill")) { [weak self] action in
|
||||
subMenuActions.append(UIAction(title: VectorL10n.inviteTo(AppInfo.current.displayName), image: UIImage(systemName: "envelope")) { [weak self] action in
|
||||
self?.showInviteFriends(from: nil)
|
||||
})
|
||||
}
|
||||
|
||||
1
changelog.d/6574.bugfix
Normal file
1
changelog.d/6574.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
App Layout: updated context menus according to last design update
|
||||
Reference in New Issue
Block a user