mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Room screen header (#86)
* #35 Create `ElementNavigationController` subclass * #35 Add encryption icons * #35 Add avatar and encryption badge image to the room screen view model * #35 Create `RoomHeaderView` class * #35 Replace room title with a RoomHeaderView instance in the toolbar * #35 Add changelog * #35 Introduce `UITestScreenIdentifier` and refactor ui tests * #35 Fix old tests * #35 add some tests for room screen * #35 Use svgs instead of pngs * #35 Fix PR remarks
This commit is contained in:
@@ -19,6 +19,8 @@ import SwiftUI
|
||||
struct RoomScreenCoordinatorParameters {
|
||||
let timelineController: RoomTimelineControllerProtocol
|
||||
let roomName: String?
|
||||
let roomAvatar: UIImage?
|
||||
let roomEncryptionBadge: UIImage?
|
||||
}
|
||||
|
||||
final class RoomScreenCoordinator: Coordinator, Presentable {
|
||||
@@ -43,7 +45,9 @@ final class RoomScreenCoordinator: Coordinator, Presentable {
|
||||
|
||||
let viewModel = RoomScreenViewModel(timelineController: parameters.timelineController,
|
||||
timelineViewFactory: RoomTimelineViewFactory(),
|
||||
roomName: parameters.roomName)
|
||||
roomName: parameters.roomName,
|
||||
roomAvatar: parameters.roomAvatar,
|
||||
roomEncryptionBadge: parameters.roomEncryptionBadge)
|
||||
|
||||
let view = RoomScreen(context: viewModel.context)
|
||||
roomScreenViewModel = viewModel
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
enum RoomScreenViewModelAction {
|
||||
|
||||
@@ -35,6 +36,8 @@ enum RoomScreenViewAction {
|
||||
|
||||
struct RoomScreenViewState: BindableState {
|
||||
var roomTitle: String = ""
|
||||
var roomAvatar: UIImage?
|
||||
var roomEncryptionBadge: UIImage?
|
||||
var items: [RoomTimelineViewProvider] = []
|
||||
var isBackPaginating = false
|
||||
var bindings: RoomScreenViewStateBindings
|
||||
|
||||
@@ -31,11 +31,16 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
|
||||
init(timelineController: RoomTimelineControllerProtocol,
|
||||
timelineViewFactory: RoomTimelineViewFactoryProtocol,
|
||||
roomName: String?) {
|
||||
roomName: String?,
|
||||
roomAvatar: UIImage? = nil,
|
||||
roomEncryptionBadge: UIImage? = nil) {
|
||||
self.timelineController = timelineController
|
||||
self.timelineViewFactory = timelineViewFactory
|
||||
|
||||
super.init(initialViewState: RoomScreenViewState(roomTitle: roomName ?? "Unknown room 💥", bindings: RoomScreenViewStateBindings(composerText: "")))
|
||||
super.init(initialViewState: RoomScreenViewState(roomTitle: roomName ?? "Unknown room 💥",
|
||||
roomAvatar: roomAvatar,
|
||||
roomEncryptionBadge: roomEncryptionBadge,
|
||||
bindings: .init(composerText: "")))
|
||||
|
||||
timelineController.callbacks
|
||||
.receive(on: DispatchQueue.main)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// RoomHeaderView.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Ismail on 21.06.2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import Combine
|
||||
|
||||
import Introspect
|
||||
|
||||
struct RoomHeaderView: View {
|
||||
|
||||
@ObservedObject var context: RoomScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 8) {
|
||||
roomAvatar
|
||||
Text(context.viewState.roomTitle)
|
||||
.font(.element.headline)
|
||||
.accessibilityIdentifier("roomNameLabel")
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private var roomAvatar: some View {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
roomAvatarImage
|
||||
.clipShape(Circle())
|
||||
|
||||
if let encryptionBadge = context.viewState.roomEncryptionBadge {
|
||||
Image(uiImage: encryptionBadge)
|
||||
.accessibilityIdentifier("encryptionBadgeIcon")
|
||||
}
|
||||
}
|
||||
.frame(width: 32.0, height: 32.0)
|
||||
}
|
||||
|
||||
@ViewBuilder private var roomAvatarImage: some View {
|
||||
if let avatar = context.viewState.roomAvatar {
|
||||
Image(uiImage: avatar)
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.accessibilityIdentifier("roomAvatarImage")
|
||||
} else {
|
||||
PlaceholderAvatarImage(firstCharacter: String(context.viewState.roomTitle.first ?? Character("")))
|
||||
.accessibilityIdentifier("roomAvatarPlaceholderImage")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct RoomHeaderView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
bodyPlain.preferredColorScheme(.light)
|
||||
bodyPlain.preferredColorScheme(.dark)
|
||||
bodyEncrypted.preferredColorScheme(.light)
|
||||
bodyEncrypted.preferredColorScheme(.dark)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
static var bodyPlain: some View {
|
||||
let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
|
||||
timelineViewFactory: RoomTimelineViewFactory(),
|
||||
roomName: "Some Room name",
|
||||
roomAvatar: Asset.Images.appLogo.image
|
||||
)
|
||||
|
||||
RoomHeaderView(context: viewModel.context)
|
||||
.previewLayout(.sizeThatFits)
|
||||
.padding()
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
static var bodyEncrypted: some View {
|
||||
let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
|
||||
timelineViewFactory: RoomTimelineViewFactory(),
|
||||
roomName: "Some Room name",
|
||||
roomAvatar: Asset.Images.appLogo.image,
|
||||
roomEncryptionBadge: Asset.Images.encryptionTrusted.image
|
||||
)
|
||||
|
||||
RoomHeaderView(context: viewModel.context)
|
||||
.previewLayout(.sizeThatFits)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,12 @@ struct RoomScreen: View {
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.navigationTitle(context.viewState.roomTitle)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
RoomHeaderView(context: context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func sendMessage() {
|
||||
|
||||
Reference in New Issue
Block a user