Skip to content

Commit

Permalink
[Spaces] M10.7 Explore rooms #4571
Browse files Browse the repository at this point in the history
- UI updates after design changes
  • Loading branch information
gileluard committed Aug 15, 2021
1 parent 82f4d57 commit a968bab
Show file tree
Hide file tree
Showing 19 changed files with 471 additions and 88 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "space_room_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions Riot/Assets/en.lproj/Vector.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,14 @@ Tap the + to start adding people.";
"leave_space_message" = "Are you sure you want to leave %@?";
"spaces_explore_rooms" = "Explore rooms";
"spaces_suggested_room" = "Suggested";
"space_tag" = "space";
"spaces_empty_space_title" = "This space has no rooms (yet)";
"spaces_empty_space_detail" = "Some rooms may be hidden because they’re private and you need an invite.";
"spaces_no_result_found_title" = "No results found";
"spaces_no_room_found_detail" = "Some results may be hidden because they’re private and you need an invite to join them.";
"spaces_no_member_found_detail" = "Looking for someone not in Space name? For now, you can invite them on web or desktop.";
"spaces_coming_soon_title" = "Coming soon";
"spaces_coming_soon_detail" = "This feature hasn’t been implemented here, but it’s on the way. For now, you can do that on your computer.";

// Mark: Avatar

Expand Down
1 change: 1 addition & 0 deletions Riot/Generated/Images.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ internal enum Asset {
internal static let spaceMenuLeave = ImageAsset(name: "space_menu_leave")
internal static let spaceMenuMembers = ImageAsset(name: "space_menu_members")
internal static let spaceMenuRooms = ImageAsset(name: "space_menu_rooms")
internal static let spaceRoomIcon = ImageAsset(name: "space_room_icon")
internal static let spaceUserIcon = ImageAsset(name: "space_user_icon")
internal static let spacesMore = ImageAsset(name: "spaces_more")
internal static let tabFavourites = ImageAsset(name: "tab_favourites")
Expand Down
32 changes: 32 additions & 0 deletions Riot/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4714,6 +4714,26 @@ internal enum VectorL10n {
internal static var spaceFeatureUnavailableTitle: String {
return VectorL10n.tr("Vector", "space_feature_unavailable_title")
}
/// space
internal static var spaceTag: String {
return VectorL10n.tr("Vector", "space_tag")
}
/// This feature hasn’t been implemented here, but it’s on the way. For now, you can do that on your computer.
internal static var spacesComingSoonDetail: String {
return VectorL10n.tr("Vector", "spaces_coming_soon_detail")
}
/// Coming soon
internal static var spacesComingSoonTitle: String {
return VectorL10n.tr("Vector", "spaces_coming_soon_title")
}
/// Some rooms may be hidden because they’re private and you need an invite.
internal static var spacesEmptySpaceDetail: String {
return VectorL10n.tr("Vector", "spaces_empty_space_detail")
}
/// This space has no rooms (yet)
internal static var spacesEmptySpaceTitle: String {
return VectorL10n.tr("Vector", "spaces_empty_space_title")
}
/// Explore rooms
internal static var spacesExploreRooms: String {
return VectorL10n.tr("Vector", "spaces_explore_rooms")
Expand All @@ -4726,6 +4746,18 @@ internal enum VectorL10n {
internal static var spacesLeftPanelTitle: String {
return VectorL10n.tr("Vector", "spaces_left_panel_title")
}
/// Looking for someone not in Space name? For now, you can invite them on web or desktop.
internal static var spacesNoMemberFoundDetail: String {
return VectorL10n.tr("Vector", "spaces_no_member_found_detail")
}
/// No results found
internal static var spacesNoResultFoundTitle: String {
return VectorL10n.tr("Vector", "spaces_no_result_found_title")
}
/// Some results may be hidden because they’re private and you need an invite to join them.
internal static var spacesNoRoomFoundDetail: String {
return VectorL10n.tr("Vector", "spaces_no_room_found_detail")
}
/// Suggested
internal static var spacesSuggestedRoom: String {
return VectorL10n.tr("Vector", "spaces_suggested_room")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<outlet property="delegate" destination="V8j-Lb-PgC" id="MCU-dH-BVp"/>
</connections>
</searchBar>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="Ky8-xS-gvY">
<tableView clipsSubviews="YES" alpha="0.0" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="Ky8-xS-gvY">
<rect key="frame" x="0.0" y="95" width="414" height="801"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<connections>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ final class ShowSpaceExploreRoomViewController: UIViewController {
static let estimatedRowHeight: CGFloat = 64
}

// MARK: - Properties

// MARK: Outlets

@IBOutlet private var tableView: UITableView!
Expand All @@ -40,19 +38,35 @@ final class ShowSpaceExploreRoomViewController: UIViewController {
private var errorPresenter: MXKErrorPresentation!
private var activityPresenter: ActivityIndicatorPresenter!
private var titleView: MainTitleView!
private var emptyView: RootTabEmptyView!
private var plusButtonImageView: UIImageView!

private var itemDataList: [SpaceExploreRoomListItemViewData] = [] {
didSet {
tableView.reloadData()
}
}

private var emptyViewArtwork: UIImage {
return ThemeService.shared().isCurrentThemeDark() ? Asset.Images.roomsEmptyScreenArtworkDark.image : Asset.Images.roomsEmptyScreenArtwork.image
}

private var scrollViewHidden = true {
didSet {
UIView.animate(withDuration: 0.2) {
self.tableView.alpha = self.scrollViewHidden ? 0 : 1
self.emptyView.alpha = self.scrollViewHidden ? 1 : 0
}
}
}

// MARK: - Setup

class func instantiate(with viewModel: ShowSpaceExploreRoomViewModelType) -> ShowSpaceExploreRoomViewController {
let viewController = StoryboardScene.ShowSpaceExploreRoomViewController.initialScene.instantiate()
viewController.viewModel = viewModel
viewController.theme = ThemeService.shared().theme
viewController.emptyView = RootTabEmptyView.instantiate()
return viewController
}

Expand All @@ -74,6 +88,10 @@ final class ShowSpaceExploreRoomViewController: UIViewController {
self.viewModel.viewDelegate = self

self.viewModel.process(viewAction: .loadData)

self.emptyView.frame = CGRect(x: 0, y: self.searchBar.frame.maxY, width: self.view.bounds.width, height: self.view.bounds.height - self.searchBar.frame.maxY)
self.emptyView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
self.view.insertSubview(self.emptyView, at: 0)
}

override func viewWillAppear(_ animated: Bool) {
Expand Down Expand Up @@ -106,6 +124,7 @@ final class ShowSpaceExploreRoomViewController: UIViewController {
self.titleView.update(theme: theme)
self.tableView.backgroundColor = theme.colors.background
self.tableView.reloadData()
self.emptyView.update(theme: theme)
}

private func registerThemeServiceDidChangeThemeNotification() {
Expand All @@ -123,14 +142,18 @@ final class ShowSpaceExploreRoomViewController: UIViewController {

self.navigationItem.rightBarButtonItem = cancelBarButtonItem

self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
self.vc_removeBackTitle()

self.titleView = MainTitleView()
self.titleView.titleLabel.text = VectorL10n.titleRooms
self.navigationItem.titleView = self.titleView

self.tableView.keyboardDismissMode = .interactive
self.setupTableView()

self.emptyView.fill(with: self.emptyViewArtwork, title: VectorL10n.roomsEmptyViewTitle, informationText: VectorL10n.roomsEmptyViewInformation)

self.plusButtonImageView = self.vc_addFAB(withImage: Asset.Images.roomsFloatingAction.image, target: self, action: #selector(addRoomAction(semder:)))
}

private func setupTableView() {
Expand All @@ -139,6 +162,7 @@ final class ShowSpaceExploreRoomViewController: UIViewController {
self.tableView.estimatedRowHeight = Constants.estimatedRowHeight
self.tableView.allowsSelection = true
self.tableView.register(cellType: SpaceChildViewCell.self)
self.tableView.register(cellType: SpaceChildSpaceViewCell.self)
self.tableView.tableFooterView = UIView()
}

Expand All @@ -150,6 +174,10 @@ final class ShowSpaceExploreRoomViewController: UIViewController {
self.titleView.subtitleLabel.text = spaceName
case .loaded(let children):
self.renderLoaded(children: children)
case .emptySpace:
self.renderEmptySpace()
case .emptyFilterResult:
self.renderEmptyFilterResult()
case .error(let error):
self.render(error: error)
}
Expand All @@ -162,20 +190,36 @@ final class ShowSpaceExploreRoomViewController: UIViewController {
private func renderLoaded(children: [SpaceExploreRoomListItemViewData]) {
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
self.itemDataList = children
self.scrollViewHidden = false
}

private func render(error: Error) {
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil)
}

private func renderEmptySpace() {
self.emptyView.fill(with: self.emptyViewArtwork, title: VectorL10n.spacesEmptySpaceTitle, informationText: VectorL10n.spacesEmptySpaceTitle)
self.scrollViewHidden = true
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
}

private func renderEmptyFilterResult() {
self.emptyView.fill(with: self.emptyViewArtwork, title: VectorL10n.spacesNoResultFoundTitle, informationText: VectorL10n.spacesNoRoomFoundDetail)
self.scrollViewHidden = true
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
}

// MARK: - Actions

private func cancelButtonAction() {
self.viewModel.process(viewAction: .cancel)
}

@objc private func addRoomAction(semder: UIView) {
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesComingSoonTitle, message: VectorL10n.spacesComingSoonDetail, animated: true, handler: nil)
}

// MARK: - UISearchBarDelegate

override func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
Expand All @@ -195,10 +239,10 @@ extension ShowSpaceExploreRoomViewController: UITableViewDataSource {
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: SpaceChildViewCell.self)

let viewData = self.itemDataList[indexPath.row]

let cell = viewData.childInfo.roomType == .space ? tableView.dequeueReusableCell(for: indexPath, cellType: SpaceChildSpaceViewCell.self) : tableView.dequeueReusableCell(for: indexPath, cellType: SpaceChildViewCell.self)

cell.update(theme: self.theme)
cell.fill(with: viewData)
cell.selectionStyle = .none
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,15 @@ final class ShowSpaceExploreRoomViewModel: ShowSpaceExploreRoomViewModelType {
}
private var filteredItemDataList: [SpaceExploreRoomListItemViewData] = [] {
didSet {
self.update(viewState: .loaded(self.filteredItemDataList))
if self.filteredItemDataList.isEmpty {
if self.itemDataList.isEmpty {
self.update(viewState: .emptySpace)
} else {
self.update(viewState: .emptyFilterResult)
}
} else {
self.update(viewState: .loaded(self.filteredItemDataList))
}
}
}

Expand Down Expand Up @@ -95,7 +103,11 @@ final class ShowSpaceExploreRoomViewModel: ShowSpaceExploreRoomViewModelType {

switch response {
case .success(let spaceSummary):
self.itemDataList = spaceSummary.childInfos.map({ childInfo in
self.itemDataList = spaceSummary.childInfos.compactMap({ childInfo in
guard childInfo.parentIds.contains(self.spaceId) else {
return nil
}

let avatarViewData = AvatarViewData(avatarUrl: childInfo.avatarUrl, mediaManager: self.session.mediaManager, fallbackImage: .matrixItem(childInfo.childRoomId, childInfo.name))
return SpaceExploreRoomListItemViewData(childInfo: childInfo, avatarViewData: avatarViewData)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@ enum ShowSpaceExploreRoomViewState {
case loading
case spaceNameFound(_ spaceName: String)
case loaded(_ children: [SpaceExploreRoomListItemViewData])
case emptySpace
case emptyFilterResult
case error(Error)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// 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
import Reusable

class SpaceChildSpaceViewCell: SpaceChildViewCell {

@IBOutlet private weak var roomsIcon: UIImageView!
@IBOutlet private weak var roomNumberLabel: UILabel!
@IBOutlet private weak var spaceTagView: UIView!

// MARK: - Life cycle

override func awakeFromNib() {
super.awakeFromNib()

self.spaceTagView.layer.masksToBounds = true
self.spaceTagView.layer.cornerRadius = 2
}

// MARK: - Public

override func fill(with viewData: SpaceExploreRoomListItemViewData) {
super.fill(with: viewData)

self.roomNumberLabel.text = "\(viewData.childInfo.childrenIds.count)"
self.topicLabel.text = VectorL10n.spaceTag
}

override func update(theme: Theme) {
super.update(theme: theme)

self.roomNumberLabel.font = theme.fonts.caption1
self.roomNumberLabel.textColor = theme.colors.tertiaryContent
self.roomsIcon.tintColor = theme.colors.tertiaryContent
self.spaceTagView.backgroundColor = theme.colors.quinaryContent
}
}
Loading

0 comments on commit a968bab

Please sign in to comment.