mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
[Spaces] M10.4.1 Home space data filtering #4570
- Added settings menu for Home space
This commit is contained in:
parent
9e331722cc
commit
abfddff1cc
19 changed files with 259 additions and 16 deletions
26
Riot/Assets/Images.xcassets/Spaces/space_private_icon.imageset/Contents.json
vendored
Normal file
26
Riot/Assets/Images.xcassets/Spaces/space_private_icon.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "space_private_icon.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "space_private_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "space_private_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
BIN
Riot/Assets/Images.xcassets/Spaces/space_private_icon.imageset/space_private_icon.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Spaces/space_private_icon.imageset/space_private_icon.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1,003 B |
BIN
Riot/Assets/Images.xcassets/Spaces/space_private_icon.imageset/space_private_icon@2x.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Spaces/space_private_icon.imageset/space_private_icon@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
Riot/Assets/Images.xcassets/Spaces/space_private_icon.imageset/space_private_icon@3x.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Spaces/space_private_icon.imageset/space_private_icon@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -1718,6 +1718,7 @@ Tap the + to start adding people.";
|
||||||
"spaces_coming_soon_detail" = "This feature hasn’t been implemented here, but it’s on the way. For now, you can do that with Element on your computer.";
|
"spaces_coming_soon_detail" = "This feature hasn’t been implemented here, but it’s on the way. For now, you can do that with Element on your computer.";
|
||||||
"space_participants_action_remove" = "Remove from this space";
|
"space_participants_action_remove" = "Remove from this space";
|
||||||
"space_participants_action_ban" = "Ban from this space";
|
"space_participants_action_ban" = "Ban from this space";
|
||||||
|
"space_home_show_all_rooms" = "Show all rooms";
|
||||||
|
|
||||||
"space_private_join_rule" = "Private space";
|
"space_private_join_rule" = "Private space";
|
||||||
"space_public_join_rule" = "Public space";
|
"space_public_join_rule" = "Public space";
|
||||||
|
|
|
@ -192,6 +192,7 @@ internal enum Asset {
|
||||||
internal static let spaceMenuLeave = ImageAsset(name: "space_menu_leave")
|
internal static let spaceMenuLeave = ImageAsset(name: "space_menu_leave")
|
||||||
internal static let spaceMenuMembers = ImageAsset(name: "space_menu_members")
|
internal static let spaceMenuMembers = ImageAsset(name: "space_menu_members")
|
||||||
internal static let spaceMenuRooms = ImageAsset(name: "space_menu_rooms")
|
internal static let spaceMenuRooms = ImageAsset(name: "space_menu_rooms")
|
||||||
|
internal static let spacePrivateIcon = ImageAsset(name: "space_private_icon")
|
||||||
internal static let spaceRoomIcon = ImageAsset(name: "space_room_icon")
|
internal static let spaceRoomIcon = ImageAsset(name: "space_room_icon")
|
||||||
internal static let spaceTypeIcon = ImageAsset(name: "space_type_icon")
|
internal static let spaceTypeIcon = ImageAsset(name: "space_type_icon")
|
||||||
internal static let spaceUserIcon = ImageAsset(name: "space_user_icon")
|
internal static let spaceUserIcon = ImageAsset(name: "space_user_icon")
|
||||||
|
@ -222,6 +223,7 @@ internal struct ImageAsset {
|
||||||
internal typealias Image = UIImage
|
internal typealias Image = UIImage
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@available(iOS 8.0, tvOS 9.0, watchOS 2.0, macOS 10.7, *)
|
||||||
internal var image: Image {
|
internal var image: Image {
|
||||||
let bundle = BundleToken.bundle
|
let bundle = BundleToken.bundle
|
||||||
#if os(iOS) || os(tvOS)
|
#if os(iOS) || os(tvOS)
|
||||||
|
@ -233,13 +235,25 @@ internal struct ImageAsset {
|
||||||
let image = Image(named: name)
|
let image = Image(named: name)
|
||||||
#endif
|
#endif
|
||||||
guard let result = image else {
|
guard let result = image else {
|
||||||
fatalError("Unable to load image named \(name).")
|
fatalError("Unable to load image asset named \(name).")
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(iOS) || os(tvOS)
|
||||||
|
@available(iOS 8.0, tvOS 9.0, *)
|
||||||
|
internal func image(compatibleWith traitCollection: UITraitCollection) -> Image {
|
||||||
|
let bundle = BundleToken.bundle
|
||||||
|
guard let result = Image(named: name, in: bundle, compatibleWith: traitCollection) else {
|
||||||
|
fatalError("Unable to load image asset named \(name).")
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal extension ImageAsset.Image {
|
internal extension ImageAsset.Image {
|
||||||
|
@available(iOS 8.0, tvOS 9.0, watchOS 2.0, *)
|
||||||
@available(macOS, deprecated,
|
@available(macOS, deprecated,
|
||||||
message: "This initializer is unsafe on macOS, please use the ImageAsset.image property")
|
message: "This initializer is unsafe on macOS, please use the ImageAsset.image property")
|
||||||
convenience init!(asset: ImageAsset) {
|
convenience init!(asset: ImageAsset) {
|
||||||
|
|
|
@ -4855,6 +4855,10 @@ public class VectorL10n: NSObject {
|
||||||
public static var spaceFeatureUnavailableTitle: String {
|
public static var spaceFeatureUnavailableTitle: String {
|
||||||
return VectorL10n.tr("Vector", "space_feature_unavailable_title")
|
return VectorL10n.tr("Vector", "space_feature_unavailable_title")
|
||||||
}
|
}
|
||||||
|
/// Show all rooms
|
||||||
|
public static var spaceHomeShowAllRooms: String {
|
||||||
|
return VectorL10n.tr("Vector", "space_home_show_all_rooms")
|
||||||
|
}
|
||||||
/// Ban from this space
|
/// Ban from this space
|
||||||
public static var spaceParticipantsActionBan: String {
|
public static var spaceParticipantsActionBan: String {
|
||||||
return VectorL10n.tr("Vector", "space_participants_action_ban")
|
return VectorL10n.tr("Vector", "space_participants_action_ban")
|
||||||
|
|
|
@ -1610,7 +1610,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||||
}
|
}
|
||||||
|
|
||||||
MXLogDebug(@"[RecentsDataSource] refreshRoomsSections: Done in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000);
|
MXLogDebug(@"[RecentsDataSource] refreshRoomsSections: Done in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000);
|
||||||
MXLogDebug(@"[Spaces] refreshRoomsSections with %ld suggested room", suggestedRoomCellDataArray.count);
|
MXLogDebug(@"[RecentsDataSource] refreshRoomsSections with %ld suggested room", suggestedRoomCellDataArray.count);
|
||||||
|
|
||||||
return [[RecentsDataSourceState alloc]
|
return [[RecentsDataSourceState alloc]
|
||||||
initWithInvitesCellDataArray:invitesCellDataArray
|
initWithInvitesCellDataArray:invitesCellDataArray
|
||||||
|
|
|
@ -231,6 +231,9 @@ class SpaceDetailViewController: UIViewController {
|
||||||
let membersString = membersCount == 1 ? VectorL10n.roomTitleOneMember : VectorL10n.roomTitleMembers("\(membersCount)")
|
let membersString = membersCount == 1 ? VectorL10n.roomTitleOneMember : VectorL10n.roomTitleMembers("\(membersCount)")
|
||||||
self.spaceTypeLabel.text = "\(joinRuleString) · \(membersString)"
|
self.spaceTypeLabel.text = "\(joinRuleString) · \(membersString)"
|
||||||
|
|
||||||
|
let joinRuleIcon = parameters.joinRule == .public ? Asset.Images.spaceTypeIcon : Asset.Images.spacePrivateIcon
|
||||||
|
self.spaceTypeIconView.image = joinRuleIcon.image
|
||||||
|
|
||||||
self.inviterIdLabel.text = parameters.inviterId
|
self.inviterIdLabel.text = parameters.inviterId
|
||||||
if let inviterId = parameters.inviterId {
|
if let inviterId = parameters.inviterId {
|
||||||
self.inviterTitleLabel.text = "\(parameters.inviter?.displayname ?? inviterId) invited you"
|
self.inviterTitleLabel.text = "\(parameters.inviter?.displayname ?? inviterId) invited you"
|
||||||
|
|
|
@ -58,7 +58,7 @@ final class SpaceListViewCell: UITableViewCell, Themable, NibReusable {
|
||||||
func fill(with viewData: SpaceListItemViewData) {
|
func fill(with viewData: SpaceListItemViewData) {
|
||||||
self.avatarView.fill(with: viewData.avatarViewData)
|
self.avatarView.fill(with: viewData.avatarViewData)
|
||||||
self.titleLabel.text = viewData.title
|
self.titleLabel.text = viewData.title
|
||||||
self.moreButton.isHidden = viewData.spaceId == SpaceListViewModel.Constants.homeSpaceId || viewData.isInvite
|
self.moreButton.isHidden = viewData.isInvite
|
||||||
if viewData.isInvite {
|
if viewData.isInvite {
|
||||||
self.isBadgeAlert = true
|
self.isBadgeAlert = true
|
||||||
self.badgeLabel.isHidden = false
|
self.badgeLabel.isHidden = false
|
||||||
|
|
|
@ -91,7 +91,8 @@ final class SpaceListViewModel: SpaceListViewModelType {
|
||||||
case .moreAction(at: let indexPath, from: let sourceView):
|
case .moreAction(at: let indexPath, from: let sourceView):
|
||||||
let section = self.sections[indexPath.section]
|
let section = self.sections[indexPath.section]
|
||||||
switch section {
|
switch section {
|
||||||
case .home: break
|
case .home:
|
||||||
|
self.coordinatorDelegate?.spaceListViewModel(self, didPressMoreForSpaceWithId: Constants.homeSpaceId, from: sourceView)
|
||||||
case .spaces(let viewDataList):
|
case .spaces(let viewDataList):
|
||||||
let spaceViewData = viewDataList[indexPath.row]
|
let spaceViewData = viewDataList[indexPath.row]
|
||||||
self.coordinatorDelegate?.spaceListViewModel(self, didPressMoreForSpaceWithId: spaceViewData.spaceId, from: sourceView)
|
self.coordinatorDelegate?.spaceListViewModel(self, didPressMoreForSpaceWithId: spaceViewData.spaceId, from: sourceView)
|
||||||
|
|
21
Riot/Modules/Spaces/SpaceMenu/SpaceMenuCell.swift
Normal file
21
Riot/Modules/Spaces/SpaceMenu/SpaceMenuCell.swift
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//
|
||||||
|
// 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 SpaceMenuCell: Themable {
|
||||||
|
func fill(with viewData: SpaceMenuListItemViewData)
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import Foundation
|
||||||
/// Style of the `SpaceMenuListViewCell`
|
/// Style of the `SpaceMenuListViewCell`
|
||||||
enum SpaceMenuListItemStyle {
|
enum SpaceMenuListItemStyle {
|
||||||
case normal
|
case normal
|
||||||
|
case boolean
|
||||||
case destructive
|
case destructive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,4 +29,5 @@ struct SpaceMenuListItemViewData {
|
||||||
let style: SpaceMenuListItemStyle
|
let style: SpaceMenuListItemStyle
|
||||||
let title: String?
|
let title: String?
|
||||||
let icon: UIImage?
|
let icon: UIImage?
|
||||||
|
var value: Any?
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import Reusable
|
import Reusable
|
||||||
|
|
||||||
class SpaceMenuListViewCell: UITableViewCell, Themable, NibReusable {
|
class SpaceMenuListViewCell: UITableViewCell, SpaceMenuCell, NibReusable {
|
||||||
|
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
|
|
||||||
|
|
74
Riot/Modules/Spaces/SpaceMenu/SpaceMenuSwitchViewCell.swift
Normal file
74
Riot/Modules/Spaces/SpaceMenu/SpaceMenuSwitchViewCell.swift
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
//
|
||||||
|
// 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 Reusable
|
||||||
|
|
||||||
|
class SpaceMenuSwitchViewCell: UITableViewCell, SpaceMenuCell, NibReusable {
|
||||||
|
|
||||||
|
// MARK: - Properties
|
||||||
|
|
||||||
|
@IBOutlet private weak var titleLabel: UILabel!
|
||||||
|
@IBOutlet private weak var selectionView: UIView!
|
||||||
|
@IBOutlet private weak var switchView: UISwitch!
|
||||||
|
|
||||||
|
// MARK: - Private
|
||||||
|
|
||||||
|
private var theme: Theme?
|
||||||
|
|
||||||
|
// MARK: - Life cycle
|
||||||
|
|
||||||
|
override func awakeFromNib() {
|
||||||
|
super.awakeFromNib()
|
||||||
|
|
||||||
|
self.selectionStyle = .none
|
||||||
|
self.selectionView.layer.cornerRadius = 8.0
|
||||||
|
self.selectionView.layer.masksToBounds = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||||
|
super.setSelected(selected, animated: animated)
|
||||||
|
|
||||||
|
UIView.animate(withDuration: animated ? 0.3 : 0.0) {
|
||||||
|
self.selectionView.alpha = selected ? 1.0 : 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Public
|
||||||
|
|
||||||
|
func fill(with viewData: SpaceMenuListItemViewData) {
|
||||||
|
self.titleLabel.text = viewData.title
|
||||||
|
self.switchView.isOn = (viewData.value as? Bool) ?? false
|
||||||
|
|
||||||
|
guard let theme = self.theme else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if viewData.style == .destructive {
|
||||||
|
self.titleLabel.textColor = theme.colors.alert
|
||||||
|
} else {
|
||||||
|
self.titleLabel.textColor = theme.colors.primaryContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(theme: Theme) {
|
||||||
|
self.theme = theme
|
||||||
|
self.backgroundColor = theme.colors.background
|
||||||
|
self.titleLabel.textColor = theme.colors.primaryContent
|
||||||
|
self.titleLabel.font = theme.fonts.body
|
||||||
|
self.selectionView.backgroundColor = theme.colors.separator
|
||||||
|
}
|
||||||
|
}
|
64
Riot/Modules/Spaces/SpaceMenu/SpaceMenuSwitchViewCell.xib
Normal file
64
Riot/Modules/Spaces/SpaceMenu/SpaceMenuSwitchViewCell.xib
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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="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="64" id="tOd-GW-k0x" customClass="SpaceMenuSwitchViewCell" customModule="Riot" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tOd-GW-k0x" id="kRV-oW-j2b">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YQF-X2-MAf">
|
||||||
|
<rect key="frame" x="8" y="8" width="304" height="48"/>
|
||||||
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="48" id="f1L-gQ-B6g"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SSn-E2-PZK">
|
||||||
|
<rect key="frame" x="16" y="21.5" width="231" height="21"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<switch opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zhh-dM-9TG">
|
||||||
|
<rect key="frame" x="255" y="16.5" width="51" height="31"/>
|
||||||
|
</switch>
|
||||||
|
</subviews>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="YQF-X2-MAf" firstAttribute="top" secondItem="kRV-oW-j2b" secondAttribute="top" constant="8" id="0nO-xV-wrC"/>
|
||||||
|
<constraint firstItem="zhh-dM-9TG" firstAttribute="leading" secondItem="SSn-E2-PZK" secondAttribute="trailing" constant="8" id="3fk-BS-QhF"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="YQF-X2-MAf" secondAttribute="trailing" constant="8" id="4pu-1l-NUB"/>
|
||||||
|
<constraint firstItem="YQF-X2-MAf" firstAttribute="leading" secondItem="kRV-oW-j2b" secondAttribute="leading" constant="8" id="Dlx-2U-0pd"/>
|
||||||
|
<constraint firstItem="zhh-dM-9TG" firstAttribute="centerY" secondItem="kRV-oW-j2b" secondAttribute="centerY" id="JlX-MX-R9W"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="YQF-X2-MAf" secondAttribute="bottom" constant="8" id="fTw-ef-WYp"/>
|
||||||
|
<constraint firstItem="SSn-E2-PZK" firstAttribute="leading" secondItem="kRV-oW-j2b" secondAttribute="leading" constant="16" id="fep-GJ-roy"/>
|
||||||
|
<constraint firstItem="SSn-E2-PZK" firstAttribute="centerY" secondItem="kRV-oW-j2b" secondAttribute="centerY" id="jwX-PQ-zct"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="zhh-dM-9TG" secondAttribute="trailing" constant="16" id="rKz-yr-ejP"/>
|
||||||
|
</constraints>
|
||||||
|
</tableViewCellContentView>
|
||||||
|
<viewLayoutGuide key="safeArea" id="0Tk-ek-Uxc"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="selectionView" destination="YQF-X2-MAf" id="Y3z-Ug-Lrc"/>
|
||||||
|
<outlet property="switchView" destination="zhh-dM-9TG" id="ogf-cv-75K"/>
|
||||||
|
<outlet property="titleLabel" destination="SSn-E2-PZK" id="bS7-F2-Tfb"/>
|
||||||
|
</connections>
|
||||||
|
<point key="canvasLocation" x="137.68115942028987" y="104.46428571428571"/>
|
||||||
|
</tableViewCell>
|
||||||
|
</objects>
|
||||||
|
<resources>
|
||||||
|
<systemColor name="systemBackgroundColor">
|
||||||
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
</systemColor>
|
||||||
|
</resources>
|
||||||
|
</document>
|
|
@ -114,6 +114,17 @@ class SpaceMenuViewController: UIViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupViews() {
|
private func setupViews() {
|
||||||
|
setupTableView()
|
||||||
|
|
||||||
|
if self.spaceId == SpaceListViewModel.Constants.homeSpaceId {
|
||||||
|
let avatarViewData = AvatarViewData(matrixItemId: self.spaceId, displayName: nil, avatarUrl: nil, mediaManager: session.mediaManager, fallbackImage: .image(Asset.Images.spaceHomeIcon.image, .center))
|
||||||
|
self.avatarView.fill(with: avatarViewData)
|
||||||
|
self.titleLabel.text = VectorL10n.titleHome
|
||||||
|
self.subtitleLabel.text = VectorL10n.settingsTitle
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
guard let space = self.session.spaceService.getSpace(withId: self.spaceId), let summary = space.summary else {
|
guard let space = self.session.spaceService.getSpace(withId: self.spaceId), let summary = space.summary else {
|
||||||
MXLog.error("[SpaceMenuViewController] setupViews: no space found")
|
MXLog.error("[SpaceMenuViewController] setupViews: no space found")
|
||||||
return
|
return
|
||||||
|
@ -130,7 +141,6 @@ class SpaceMenuViewController: UIViewController {
|
||||||
|
|
||||||
self.closeButton.layer.masksToBounds = true
|
self.closeButton.layer.masksToBounds = true
|
||||||
self.closeButton.layer.cornerRadius = self.closeButton.bounds.height / 2
|
self.closeButton.layer.cornerRadius = self.closeButton.bounds.height / 2
|
||||||
setupTableView()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupTableView() {
|
private func setupTableView() {
|
||||||
|
@ -139,6 +149,7 @@ class SpaceMenuViewController: UIViewController {
|
||||||
self.tableView.estimatedRowHeight = Constants.estimatedRowHeight
|
self.tableView.estimatedRowHeight = Constants.estimatedRowHeight
|
||||||
self.tableView.allowsSelection = true
|
self.tableView.allowsSelection = true
|
||||||
self.tableView.register(cellType: SpaceMenuListViewCell.self)
|
self.tableView.register(cellType: SpaceMenuListViewCell.self)
|
||||||
|
self.tableView.register(cellType: SpaceMenuSwitchViewCell.self)
|
||||||
self.tableView.tableFooterView = UIView()
|
self.tableView.tableFooterView = UIView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +161,8 @@ class SpaceMenuViewController: UIViewController {
|
||||||
self.renderLoaded()
|
self.renderLoaded()
|
||||||
case .leaveOptions(let displayName, let isAdmin):
|
case .leaveOptions(let displayName, let isAdmin):
|
||||||
self.renderLeaveOptions(displayName: displayName, isAdmin: isAdmin)
|
self.renderLeaveOptions(displayName: displayName, isAdmin: isAdmin)
|
||||||
|
case .updateItem(let indexPath):
|
||||||
|
self.tableView.reloadRows(at: [indexPath], with: .fade)
|
||||||
case .error(let error):
|
case .error(let error):
|
||||||
self.render(error: error)
|
self.render(error: error)
|
||||||
case .deselect:
|
case .deselect:
|
||||||
|
@ -235,12 +248,15 @@ extension SpaceMenuViewController: UITableViewDataSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: SpaceMenuListViewCell.self)
|
|
||||||
|
|
||||||
let viewData = viewModel.menuItems[indexPath.row]
|
let viewData = viewModel.menuItems[indexPath.row]
|
||||||
|
|
||||||
|
let cell = viewData.style == .boolean ? tableView.dequeueReusableCell(for: indexPath, cellType: SpaceMenuSwitchViewCell.self) :
|
||||||
|
tableView.dequeueReusableCell(for: indexPath, cellType: SpaceMenuListViewCell.self)
|
||||||
|
|
||||||
|
if let cell = cell as? SpaceMenuCell {
|
||||||
cell.update(theme: self.theme)
|
cell.update(theme: self.theme)
|
||||||
cell.fill(with: viewData)
|
cell.fill(with: viewData)
|
||||||
|
}
|
||||||
|
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ class SpaceMenuViewModel: SpaceMenuViewModelType {
|
||||||
// MARK: - Enum
|
// MARK: - Enum
|
||||||
|
|
||||||
enum ActionId: String {
|
enum ActionId: String {
|
||||||
|
case showAllRoomsInHome = "showAllRoomsInHome"
|
||||||
case members = "members"
|
case members = "members"
|
||||||
case rooms = "rooms"
|
case rooms = "rooms"
|
||||||
case leave = "leave"
|
case leave = "leave"
|
||||||
|
@ -32,12 +33,14 @@ class SpaceMenuViewModel: SpaceMenuViewModelType {
|
||||||
weak var coordinatorDelegate: SpaceMenuModelViewModelCoordinatorDelegate?
|
weak var coordinatorDelegate: SpaceMenuModelViewModelCoordinatorDelegate?
|
||||||
weak var viewDelegate: SpaceMenuViewModelViewDelegate?
|
weak var viewDelegate: SpaceMenuViewModelViewDelegate?
|
||||||
|
|
||||||
var menuItems: [SpaceMenuListItemViewData] = [
|
private let spaceMenuItems: [SpaceMenuListItemViewData] = [
|
||||||
SpaceMenuListItemViewData(actionId: ActionId.members.rawValue, style: .normal, title: VectorL10n.roomDetailsPeople, icon: UIImage(named: "space_menu_members")),
|
SpaceMenuListItemViewData(actionId: ActionId.members.rawValue, style: .normal, title: VectorL10n.roomDetailsPeople, icon: Asset.Images.spaceMenuMembers.image, value: nil),
|
||||||
SpaceMenuListItemViewData(actionId: ActionId.rooms.rawValue, style: .normal, title: VectorL10n.spacesExploreRooms, icon: UIImage(named: "space_menu_rooms")),
|
SpaceMenuListItemViewData(actionId: ActionId.rooms.rawValue, style: .normal, title: VectorL10n.spacesExploreRooms, icon: Asset.Images.spaceMenuRooms.image, value: nil),
|
||||||
SpaceMenuListItemViewData(actionId: ActionId.leave.rawValue, style: .destructive, title: VectorL10n.leave, icon: UIImage(named: "space_menu_leave"))
|
SpaceMenuListItemViewData(actionId: ActionId.leave.rawValue, style: .destructive, title: VectorL10n.leave, icon: Asset.Images.spaceMenuLeave.image, value: nil)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
var menuItems: [SpaceMenuListItemViewData] = []
|
||||||
|
|
||||||
private let session: MXSession
|
private let session: MXSession
|
||||||
private let spaceId: String
|
private let spaceId: String
|
||||||
|
|
||||||
|
@ -46,6 +49,14 @@ class SpaceMenuViewModel: SpaceMenuViewModelType {
|
||||||
init(session: MXSession, spaceId: String) {
|
init(session: MXSession, spaceId: String) {
|
||||||
self.session = session
|
self.session = session
|
||||||
self.spaceId = spaceId
|
self.spaceId = spaceId
|
||||||
|
|
||||||
|
if spaceId != SpaceListViewModel.Constants.homeSpaceId {
|
||||||
|
self.menuItems = spaceMenuItems
|
||||||
|
} else {
|
||||||
|
self.menuItems = [
|
||||||
|
SpaceMenuListItemViewData(actionId: ActionId.showAllRoomsInHome.rawValue, style: .boolean, title: VectorL10n.spaceHomeShowAllRooms, icon: nil, value: MXKAppSettings.standard().isShowAllRoomsInHomeEnabled)
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
@ -55,7 +66,7 @@ class SpaceMenuViewModel: SpaceMenuViewModelType {
|
||||||
case .dismiss:
|
case .dismiss:
|
||||||
self.coordinatorDelegate?.spaceMenuViewModelDidDismiss(self)
|
self.coordinatorDelegate?.spaceMenuViewModelDidDismiss(self)
|
||||||
case .selectRow(at: let indexPath):
|
case .selectRow(at: let indexPath):
|
||||||
self.processAction(with: menuItems[indexPath.row].actionId)
|
self.processAction(with: menuItems[indexPath.row].actionId, at: indexPath)
|
||||||
case .leaveSpaceAndKeepRooms:
|
case .leaveSpaceAndKeepRooms:
|
||||||
self.leaveSpaceAndKeepRooms()
|
self.leaveSpaceAndKeepRooms()
|
||||||
case .leaveSpaceAndLeaveRooms:
|
case .leaveSpaceAndLeaveRooms:
|
||||||
|
@ -65,9 +76,14 @@ class SpaceMenuViewModel: SpaceMenuViewModelType {
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func processAction(with actionStringId: String) {
|
private func processAction(with actionStringId: String, at indexPath: IndexPath) {
|
||||||
let actionId = ActionId(rawValue: actionStringId)
|
let actionId = ActionId(rawValue: actionStringId)
|
||||||
switch actionId {
|
switch actionId {
|
||||||
|
case .showAllRoomsInHome:
|
||||||
|
MXKAppSettings.standard().isShowAllRoomsInHomeEnabled = !MXKAppSettings.standard().isShowAllRoomsInHomeEnabled
|
||||||
|
self.menuItems[indexPath.row].value = MXKAppSettings.standard().isShowAllRoomsInHomeEnabled
|
||||||
|
self.viewDelegate?.spaceMenuViewModel(self, didUpdateViewState: .deselect)
|
||||||
|
self.viewDelegate?.spaceMenuViewModel(self, didUpdateViewState: .updateItem(indexPath))
|
||||||
case .leave:
|
case .leave:
|
||||||
self.leaveSpace()
|
self.leaveSpace()
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -21,6 +21,7 @@ enum SpaceMenuViewState {
|
||||||
case loading
|
case loading
|
||||||
case loaded
|
case loaded
|
||||||
case deselect
|
case deselect
|
||||||
|
case updateItem(_ indexPath: IndexPath)
|
||||||
case leaveOptions(_ displayName: String, _ isAdmin: Bool)
|
case leaveOptions(_ displayName: String, _ isAdmin: Bool)
|
||||||
case error(Error)
|
case error(Error)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue