mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
tombstoned and upgraded rooms implementation
added tests tombstoned room avatar
This commit is contained in:
@@ -28,6 +28,7 @@ enum TimelineViewModelAction {
|
||||
case composer(action: TimelineComposerAction)
|
||||
case hasScrolled(direction: ScrollDirection)
|
||||
case viewInRoomTimeline(eventID: String)
|
||||
case displayRoom(roomID: String)
|
||||
}
|
||||
|
||||
enum TimelineViewPollAction {
|
||||
@@ -77,6 +78,8 @@ enum TimelineViewAction {
|
||||
|
||||
case hasScrolled(direction: ScrollDirection)
|
||||
case setOpenURLAction(OpenURLAction)
|
||||
|
||||
case seePredecessorTapped
|
||||
}
|
||||
|
||||
enum TimelineComposerAction {
|
||||
@@ -106,6 +109,8 @@ struct TimelineViewState: BindableState {
|
||||
var isViewSourceEnabled: Bool
|
||||
var areThreadsEnabled: Bool
|
||||
var hideTimelineMedia: Bool
|
||||
|
||||
let hasPredecessor: Bool
|
||||
|
||||
// The `pinnedEventIDs` are used only to determine if an item is already pinned or not.
|
||||
// It's updated from the room info, so it's faster than using the timeline
|
||||
|
||||
@@ -104,6 +104,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
||||
isViewSourceEnabled: appSettings.viewSourceEnabled,
|
||||
areThreadsEnabled: appSettings.threadsEnabled,
|
||||
hideTimelineMedia: hideTimelineMedia,
|
||||
hasPredecessor: roomProxy.predecessorRoom != nil,
|
||||
pinnedEventIDs: roomProxy.infoPublisher.value.pinnedEventIDs,
|
||||
emojiProvider: emojiProvider,
|
||||
mapTilerConfiguration: appSettings.mapTilerConfiguration,
|
||||
@@ -211,6 +212,9 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
||||
actionsSubject.send(.hasScrolled(direction: direction))
|
||||
case .setOpenURLAction(let action):
|
||||
state.openURL = action
|
||||
case .seePredecessorTapped:
|
||||
guard let predecessorID = roomProxy.predecessorRoom?.roomId else { return }
|
||||
actionsSubject.send(.displayRoom(roomID: predecessorID))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,11 +1022,12 @@ private extension RoomInfoProxy {
|
||||
extension TimelineViewModel {
|
||||
static let mock = mock(timelineKind: .live)
|
||||
|
||||
static func mock(timelineKind: TimelineKind = .live, timelineController: MockTimelineController? = nil) -> TimelineViewModel {
|
||||
static func mock(timelineKind: TimelineKind = .live, timelineController: MockTimelineController? = nil, hasPredecessor: Bool = false) -> TimelineViewModel {
|
||||
let clientProxyMock = ClientProxyMock(.init())
|
||||
clientProxyMock.roomSummaryForAliasReturnValue = .mock(id: "!room:matrix.org", name: "Room")
|
||||
clientProxyMock.roomSummaryForIdentifierReturnValue = .mock(id: "!room:matrix.org", name: "Room", canonicalAlias: "#room:matrix.org")
|
||||
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
|
||||
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview room", predecessor: hasPredecessor ? .init(roomId: UUID().uuidString, lastEventId: UUID().uuidString) : nil))
|
||||
return TimelineViewModel(roomProxy: roomProxy,
|
||||
focussedEventID: nil,
|
||||
timelineController: timelineController ?? MockTimelineController(timelineKind: timelineKind),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()),
|
||||
|
||||
+43
-6
@@ -5,20 +5,50 @@
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct TimelineStartRoomTimelineView: View {
|
||||
let timelineItem: TimelineStartRoomTimelineItem
|
||||
@Environment(\.timelineContext) private var context
|
||||
|
||||
var body: some View {
|
||||
Text(title)
|
||||
.font(.compound.bodySM)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.padding(.vertical, 24)
|
||||
.frame(maxWidth: .infinity)
|
||||
VStack(spacing: 14) {
|
||||
if context?.viewState.hasPredecessor == true {
|
||||
upgrade
|
||||
}
|
||||
if context?.viewState.isDirectOneToOneRoom != true {
|
||||
Text(title)
|
||||
.font(.compound.bodySM)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.padding(.bottom, 24)
|
||||
.padding(.top, context?.viewState.hasPredecessor == true ? 0 : 24)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var title: String {
|
||||
private var upgrade: some View {
|
||||
VStack(spacing: 16) {
|
||||
Text(L10n.screenRoomTimelineUpgradedRoomMessage)
|
||||
.font(.compound.bodyMD)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
Button {
|
||||
context?.send(viewAction: .seePredecessorTapped)
|
||||
} label: {
|
||||
Text(L10n.screenRoomTimelineUpgradedRoomAction)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.buttonStyle(.compound(.primary, size: .medium))
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.padding(.top, 16)
|
||||
.padding(.bottom, 8)
|
||||
.padding(.horizontal, 16)
|
||||
.highlight(borderColor: .compound.borderInfoSubtle, primaryColor: .compound.bgInfoSubtle, secondaryColor: Color.clear)
|
||||
}
|
||||
|
||||
private var title: String {
|
||||
var text = L10n.screenRoomTimelineBeginningOfRoomNoName
|
||||
if let name = timelineItem.name {
|
||||
text = L10n.screenRoomTimelineBeginningOfRoom(name)
|
||||
@@ -28,8 +58,15 @@ struct TimelineStartRoomTimelineView: View {
|
||||
}
|
||||
|
||||
struct TimelineStartRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = TimelineViewModel.mock(hasPredecessor: true)
|
||||
|
||||
static var previews: some View {
|
||||
let item = TimelineStartRoomTimelineItem(name: "Alice and Bob")
|
||||
TimelineStartRoomTimelineView(timelineItem: item)
|
||||
.previewLayout(.sizeThatFits)
|
||||
TimelineStartRoomTimelineView(timelineItem: item)
|
||||
.environment(\.timelineContext, viewModel.context)
|
||||
.previewLayout(.sizeThatFits)
|
||||
.previewDisplayName("with predecessor")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user