Skip to content

Commit

Permalink
[Spaces] Show spaces in left panel #4509
Browse files Browse the repository at this point in the history
- Display the none hierarchical list of spaces in the left panel
- Space switching when new space selected
- Refresh space list and recents data after sync
  • Loading branch information
gileluard committed Jul 15, 2021
1 parent 44a6181 commit f1da8c2
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 33 deletions.
4 changes: 4 additions & 0 deletions Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#import "PublicRoomsDirectoryDataSource.h"

@class MXSpace;

/**
List the different modes used to prepare the recents data source.
Each mode corresponds to an application tab: Home, Favourites, People and Rooms.
Expand Down Expand Up @@ -98,6 +100,8 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
*/
@property (nonatomic) PublicRoomsDirectoryDataSource *publicRoomsDirectoryDataSource;

@property (nonatomic, strong) MXSpace *currentSpace;

/**
Refresh the recents data source and notify its delegate.
*/
Expand Down
35 changes: 34 additions & 1 deletion Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,16 @@ - (instancetype)init

// Set default data and view classes
[self registerCellDataClass:RecentCellData.class forCellIdentifier:kMXKRecentCellIdentifier];

[self registerSpaceServiceDidBuildGraphNotification];
}
return self;
}

- (void)dealloc
{
[self unregisterSpaceServiceDidBuildGraphNotification];
}

#pragma mark - Properties

Expand Down Expand Up @@ -166,6 +172,13 @@ - (NSUInteger)unsentMessagesGroupDiscussionsCount
return state.unsentMessagesGroupDiscussionsCount;
}

- (void)setCurrentSpace:(MXSpace *)currentSpace
{
_currentSpace = currentSpace;
[self refreshRoomsSection:^{
[self.delegate dataSource:self didCellChange:nil];
}];
}

#pragma mark -

Expand Down Expand Up @@ -213,6 +226,23 @@ - (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)fr
return stickyHeader;
}

#pragma mark - Space Service notifications

- (void)registerSpaceServiceDidBuildGraphNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(spaceServiceDidBuildGraphNotification:) name:MXSpaceService.didBuildSpaceGraph object:nil];
}

- (void)spaceServiceDidBuildGraphNotification:(NSNotification*)notification
{
[self forceRefresh];
}

- (void)unregisterSpaceServiceDidBuildGraphNotification
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:MXSpaceService.didBuildSpaceGraph object:nil];
}

#pragma mark - Key backup setup banner

- (void)registerKeyBackupStateDidChangeNotification
Expand Down Expand Up @@ -1204,7 +1234,10 @@ - (void)refreshRoomsSection:(void (^)(void))onComplete;
for (NSUInteger index = 0; index < count; index++)
{
id<MXKRecentCellDataStoring> cell = [recentsDataSource cellDataAtIndex:index];
[cells addObject:cell];
if (self.currentSpace == nil || [self.currentSpace isRoomAChildWithRoomId:cell.roomSummary.roomId])
{
[cells addObject:cell];
}
}

MXWeakify(self);
Expand Down
10 changes: 8 additions & 2 deletions Riot/Modules/Spaces/SpaceList/SpaceListViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,25 @@ final class SpaceListViewCell: UITableViewCell, Themable, NibReusable {

@IBOutlet private weak var avatarView: SpaceAvatarView!
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var selectionView: UIView!

private var theme: Theme?

// MARK: - Life cycle

override func awakeFromNib() {
super.awakeFromNib()
// Initialization code

self.selectionView.layer.cornerRadius = 8.0
self.selectionView.layer.masksToBounds = true
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
UIView.animate(withDuration: animated ? 0.3 : 0.0) {
self.selectionView.alpha = selected ? 1.0 : 0.0
}
}

// MARK: - Public
Expand All @@ -52,5 +57,6 @@ final class SpaceListViewCell: UITableViewCell, Themable, NibReusable {
self.avatarView.update(theme: theme)
self.titleLabel.textColor = theme.colors.primaryContent
self.titleLabel.font = theme.fonts.bodySB
self.selectionView.backgroundColor = theme.colors.separator
}
}
43 changes: 28 additions & 15 deletions Riot/Modules/Spaces/SpaceList/SpaceListViewCell.xib
Original file line number Diff line number Diff line change
@@ -1,54 +1,67 @@
<?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" useSafeAreas="YES" colorMatched="YES">
<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="17703"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.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"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="44" id="KGk-i7-Jjw" customClass="SpaceListViewCell" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="58" id="KGk-i7-Jjw" customClass="SpaceListViewCell" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="58"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" ambiguous="YES" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="58"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="TZK-rU-aCS">
<rect key="frame" x="11" y="14" width="293" height="30"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lBS-QH-Kbp" customClass="SpaceAvatarView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="20" y="5" width="36" height="36"/>
<rect key="frame" x="18" y="11" width="32" height="32"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="36" id="oEn-qb-dCA"/>
<constraint firstAttribute="height" constant="32" id="oEn-qb-dCA"/>
<constraint firstAttribute="width" secondItem="lBS-QH-Kbp" secondAttribute="height" multiplier="1:1" id="vue-Qr-wt6"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VMB-P3-ogn">
<rect key="frame" x="71" y="12.5" width="234" height="21"/>
<rect key="frame" x="66" y="18.5" width="239" height="17"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="lBS-QH-Kbp" secondAttribute="bottom" constant="5" id="GCa-yL-d8S"/>
<constraint firstItem="VMB-P3-ogn" firstAttribute="leading" secondItem="lBS-QH-Kbp" secondAttribute="trailing" constant="15" id="Jfh-Ex-s45"/>
<constraint firstAttribute="bottom" secondItem="lBS-QH-Kbp" secondAttribute="bottom" constant="11" id="GCa-yL-d8S"/>
<constraint firstItem="TZK-rU-aCS" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="1" id="GDx-I8-LPX"/>
<constraint firstItem="VMB-P3-ogn" firstAttribute="leading" secondItem="lBS-QH-Kbp" secondAttribute="trailing" constant="16" id="Jfh-Ex-s45"/>
<constraint firstAttribute="bottom" secondItem="TZK-rU-aCS" secondAttribute="bottom" constant="1" id="O09-dX-GuR"/>
<constraint firstAttribute="trailing" secondItem="VMB-P3-ogn" secondAttribute="trailing" constant="15" id="OTN-cf-dx9"/>
<constraint firstAttribute="trailing" secondItem="TZK-rU-aCS" secondAttribute="trailing" constant="16" id="ST4-p9-7RB"/>
<constraint firstItem="VMB-P3-ogn" firstAttribute="centerY" secondItem="lBS-QH-Kbp" secondAttribute="centerY" id="Vfj-Bt-ghR"/>
<constraint firstItem="VMB-P3-ogn" firstAttribute="top" relation="greaterThanOrEqual" secondItem="H2p-sc-9uM" secondAttribute="top" constant="5" id="dRr-G6-Yhy"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="VMB-P3-ogn" secondAttribute="bottom" constant="5" id="hl6-be-Xzg"/>
<constraint firstItem="lBS-QH-Kbp" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="20" id="m8q-jc-lxH"/>
<constraint firstItem="lBS-QH-Kbp" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="5" id="zSD-gu-4Kd"/>
<constraint firstItem="TZK-rU-aCS" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="11" id="Xm8-aq-LMK"/>
<constraint firstItem="lBS-QH-Kbp" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="18" id="m8q-jc-lxH"/>
<constraint firstItem="lBS-QH-Kbp" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="11" id="zSD-gu-4Kd"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="avatarView" destination="lBS-QH-Kbp" id="UYd-1N-Mn6"/>
<outlet property="selectionView" destination="TZK-rU-aCS" id="VCe-2o-h8G"/>
<outlet property="titleLabel" destination="VMB-P3-ogn" id="lDY-8e-Y8H"/>
</connections>
<point key="canvasLocation" x="137.68115942028987" y="97.767857142857139"/>
<point key="canvasLocation" x="137.68115942028987" y="102.45535714285714"/>
</tableViewCell>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
19 changes: 15 additions & 4 deletions Riot/Modules/Spaces/SpaceList/SpaceListViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ final class SpaceListViewController: UIViewController {
private var activityPresenter: ActivityIndicatorPresenter!

private var sections: [SpaceListSection] = []
private var selectedIndexPath: IndexPath = IndexPath(row: 0, section: 0)

// MARK: - Setup

Expand Down Expand Up @@ -100,6 +101,7 @@ final class SpaceListViewController: UIViewController {
self.tableView.separatorStyle = .none
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = Constants.estimatedRowHeight
self.tableView.allowsSelection = true
self.tableView.register(cellType: SpaceListViewCell.self)
self.tableView.tableFooterView = UIView()
}
Expand All @@ -117,12 +119,16 @@ final class SpaceListViewController: UIViewController {

private func renderLoading() {
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
if let selectedRow = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: selectedRow, animated: true)
}
}

private func renderLoaded(sections: [SpaceListSection]) {
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
self.sections = sections
self.tableView.reloadData()
self.tableView.selectRow(at: selectedIndexPath, animated: true, scrollPosition: .none)
}

private func render(error: Error) {
Expand All @@ -134,10 +140,14 @@ final class SpaceListViewController: UIViewController {

// MARK: - SpaceListViewModelViewDelegate
extension SpaceListViewController: SpaceListViewModelViewDelegate {

func spaceListViewModel(_ viewModel: SpaceListViewModelType, didUpdateViewState viewSate: SpaceListViewState) {
self.render(viewState: viewSate)
}

func spaceListViewModel(_ viewModel: SpaceListViewModelType, didSelectSpaceAt indexPath: IndexPath) {
self.selectedIndexPath = IndexPath(row: indexPath.row, section: indexPath.section)
self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
}
}

// MARK: - UITableViewDataSource
Expand Down Expand Up @@ -179,7 +189,7 @@ extension SpaceListViewController: UITableViewDataSource {

cell.update(theme: self.theme)
cell.fill(with: viewData)
cell.selectionStyle = .blue
cell.selectionStyle = .none

return cell
}
Expand All @@ -189,7 +199,8 @@ extension SpaceListViewController: UITableViewDataSource {
extension SpaceListViewController: UITableViewDelegate {

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
self.viewModel.process(viewAction: .selectRow(at: indexPath))
if selectedIndexPath != indexPath {
self.viewModel.process(viewAction: .selectRow(at: indexPath))
}
}
}
24 changes: 21 additions & 3 deletions Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ final class SpaceListViewModel: SpaceListViewModelType {

init(session: MXSession) {
self.session = session

NotificationCenter.default.addObserver(self, selector: #selector(self.sessionDidSync(notification:)), name: MXSpaceService.didBuildSpaceGraph, object: nil)

}

deinit {
self.cancelOperations()
NotificationCenter.default.removeObserver(self)
}

// MARK: - Public
Expand All @@ -59,20 +63,23 @@ final class SpaceListViewModel: SpaceListViewModelType {
let spaceViewData = viewDataList[indexPath.row]
self.selectSpace(with: spaceViewData.spaceId)
}
self.viewDelegate?.spaceListViewModel(self, didSelectSpaceAt: indexPath)
}
}

// MARK: - Private

@objc private func sessionDidSync(notification: Notification) {
loadData()
}

private func loadData() {

self.update(viewState: .loading)

let homeViewData = self.createHomeViewData()

// TODO: Manage space list
let spacesViewDataList: [SpaceListItemViewData] = [
]
let spacesViewDataList = getSpacesViewData()

let sections: [SpaceListSection] = [
.home(homeViewData),
Expand Down Expand Up @@ -100,6 +107,17 @@ final class SpaceListViewModel: SpaceListViewModelType {
return homeViewData
}

private func getSpacesViewData() -> [SpaceListItemViewData] {
return session.spaceService.spaces.compactMap { space -> SpaceListItemViewData? in
guard let summary = space.summary else {
return nil
}
let avatarViewData = AvatarViewData(avatarUrl: summary.avatar, mediaManager: self.session.mediaManager, fallbackImage: .matrixItem(summary.roomId, summary.displayname))
return SpaceListItemViewData(spaceId: summary.roomId,
title: summary.displayname, avatarViewData: avatarViewData)
}
}

private func update(viewState: SpaceListViewState) {
self.viewDelegate?.spaceListViewModel(self, didUpdateViewState: viewState)
}
Expand Down
1 change: 1 addition & 0 deletions Riot/Modules/Spaces/SpaceList/SpaceListViewModelType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Foundation

protocol SpaceListViewModelViewDelegate: class {
func spaceListViewModel(_ viewModel: SpaceListViewModelType, didUpdateViewState viewSate: SpaceListViewState)
func spaceListViewModel(_ viewModel: SpaceListViewModelType, didSelectSpaceAt indexPath: IndexPath)
}

protocol SpaceListViewModelCoordinatorDelegate: class {
Expand Down
Loading

0 comments on commit f1da8c2

Please sign in to comment.