mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
This commit is contained in:
@@ -22,7 +22,6 @@ typealias RoomScreenViewModelType = StateStoreViewModel<RoomScreenViewState, Roo
|
|||||||
class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol {
|
class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol {
|
||||||
private enum Constants {
|
private enum Constants {
|
||||||
static let backPaginationPageSize: UInt = 20
|
static let backPaginationPageSize: UInt = 20
|
||||||
static let backPaginationIndicatorID = "RoomBackPagination"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private let timelineController: RoomTimelineControllerProtocol
|
private let timelineController: RoomTimelineControllerProtocol
|
||||||
@@ -30,11 +29,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
private let mediaProvider: MediaProviderProtocol
|
private let mediaProvider: MediaProviderProtocol
|
||||||
|
|
||||||
// MARK: - Setup
|
// MARK: - Setup
|
||||||
|
|
||||||
deinit {
|
|
||||||
ServiceLocator.shared.userNotificationController.retractNotificationWithId(Constants.backPaginationIndicatorID)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(timelineController: RoomTimelineControllerProtocol,
|
init(timelineController: RoomTimelineControllerProtocol,
|
||||||
timelineViewFactory: RoomTimelineViewFactoryProtocol,
|
timelineViewFactory: RoomTimelineViewFactoryProtocol,
|
||||||
mediaProvider: MediaProviderProtocol,
|
mediaProvider: MediaProviderProtocol,
|
||||||
@@ -66,13 +61,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
self.state.items[viewIndex] = timelineViewFactory.buildTimelineViewFor(timelineItem: timelineItem)
|
self.state.items[viewIndex] = timelineViewFactory.buildTimelineViewFor(timelineItem: timelineItem)
|
||||||
case .startedBackPaginating:
|
case .startedBackPaginating:
|
||||||
self.state.isBackPaginating = true
|
self.state.isBackPaginating = true
|
||||||
ServiceLocator.shared.userNotificationController.submitNotification(UserNotification(id: Constants.backPaginationIndicatorID,
|
|
||||||
type: .toast,
|
|
||||||
title: ElementL10n.roomTimelineSyncing,
|
|
||||||
persistent: true))
|
|
||||||
case .finishedBackPaginating:
|
case .finishedBackPaginating:
|
||||||
self.state.isBackPaginating = false
|
self.state.isBackPaginating = false
|
||||||
ServiceLocator.shared.userNotificationController.retractNotificationWithId(Constants.backPaginationIndicatorID)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class TimelineTableViewController: UIViewController {
|
|||||||
didSet {
|
didSet {
|
||||||
// Paginate again if the threshold hasn't been satisfied.
|
// Paginate again if the threshold hasn't been satisfied.
|
||||||
paginateBackwardsPublisher.send(())
|
paginateBackwardsPublisher.send(())
|
||||||
|
applySnapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,37 +198,41 @@ class TimelineTableViewController: UIViewController {
|
|||||||
|
|
||||||
cell.item = timelineItem
|
cell.item = timelineItem
|
||||||
cell.contentConfiguration = UIHostingConfiguration {
|
cell.contentConfiguration = UIHostingConfiguration {
|
||||||
VStack {
|
if case .backPaginationIndicator = timelineItem {
|
||||||
if displayReactionsMenuForItemId == timelineItem.id {
|
|
||||||
TimelineItemReactionsMenuView { emoji in
|
|
||||||
coordinator.send(viewAction: .emojiTapped(emoji: emoji, itemId: timelineItem.id))
|
|
||||||
} onDisplayEmojiPicker: {
|
|
||||||
coordinator.send(viewAction: .displayEmojiPicker(itemId: timelineItem.id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timelineItem
|
timelineItem
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
} else {
|
||||||
.opacity(opacity)
|
VStack {
|
||||||
.contextMenu {
|
if displayReactionsMenuForItemId == timelineItem.id {
|
||||||
contextMenuBuilder?(timelineItem.id)
|
TimelineItemReactionsMenuView { emoji in
|
||||||
}
|
coordinator.send(viewAction: .emojiTapped(emoji: emoji, itemId: timelineItem.id))
|
||||||
.onAppear {
|
} onDisplayEmojiPicker: {
|
||||||
coordinator.send(viewAction: .itemAppeared(id: timelineItem.id))
|
coordinator.send(viewAction: .displayEmojiPicker(itemId: timelineItem.id))
|
||||||
}
|
}
|
||||||
.onDisappear {
|
|
||||||
coordinator.send(viewAction: .itemDisappeared(id: timelineItem.id))
|
|
||||||
}
|
|
||||||
.environment(\.openURL, OpenURLAction { url in
|
|
||||||
coordinator.send(viewAction: .linkClicked(url: url))
|
|
||||||
return .systemAction
|
|
||||||
})
|
|
||||||
.onTapGesture(count: 2) {
|
|
||||||
coordinator.send(viewAction: .displayReactionsMenuForItemId(itemId: timelineItem.id))
|
|
||||||
}
|
|
||||||
.onTapGesture {
|
|
||||||
coordinator.send(viewAction: .itemTapped(id: timelineItem.id))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timelineItem
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.opacity(opacity)
|
||||||
|
.contextMenu {
|
||||||
|
contextMenuBuilder?(timelineItem.id)
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
coordinator.send(viewAction: .itemAppeared(id: timelineItem.id))
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
coordinator.send(viewAction: .itemDisappeared(id: timelineItem.id))
|
||||||
|
}
|
||||||
|
.environment(\.openURL, OpenURLAction { url in
|
||||||
|
coordinator.send(viewAction: .linkClicked(url: url))
|
||||||
|
return .systemAction
|
||||||
|
})
|
||||||
|
.onTapGesture(count: 2) {
|
||||||
|
coordinator.send(viewAction: .displayReactionsMenuForItemId(itemId: timelineItem.id))
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
coordinator.send(viewAction: .itemTapped(id: timelineItem.id))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.margins(.all, self.timelineStyle.rowInsets)
|
.margins(.all, self.timelineStyle.rowInsets)
|
||||||
@@ -248,6 +253,8 @@ class TimelineTableViewController: UIViewController {
|
|||||||
let previousLayout = layout()
|
let previousLayout = layout()
|
||||||
|
|
||||||
var snapshot = NSDiffableDataSourceSnapshot<TimelineSection, RoomTimelineViewProvider>()
|
var snapshot = NSDiffableDataSourceSnapshot<TimelineSection, RoomTimelineViewProvider>()
|
||||||
|
snapshot.appendSections([.loadingIndicator])
|
||||||
|
snapshot.appendItems([.backPaginationIndicator(isBackPaginating)])
|
||||||
snapshot.appendSections([.main])
|
snapshot.appendSections([.main])
|
||||||
snapshot.appendItems(timelineItems)
|
snapshot.appendItems(timelineItems)
|
||||||
dataSource.apply(snapshot, animatingDifferences: false)
|
dataSource.apply(snapshot, animatingDifferences: false)
|
||||||
@@ -409,7 +416,10 @@ extension TimelineTableViewController: UITableViewDelegate {
|
|||||||
|
|
||||||
extension TimelineTableViewController {
|
extension TimelineTableViewController {
|
||||||
/// The sections of the table view used in the diffable data source.
|
/// The sections of the table view used in the diffable data source.
|
||||||
enum TimelineSection { case main }
|
enum TimelineSection {
|
||||||
|
case loadingIndicator
|
||||||
|
case main
|
||||||
|
}
|
||||||
|
|
||||||
/// A description of the timeline's layout.
|
/// A description of the timeline's layout.
|
||||||
struct LayoutDescriptor {
|
struct LayoutDescriptor {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ enum RoomTimelineViewProvider: Identifiable, Hashable {
|
|||||||
case notice(NoticeRoomTimelineItem)
|
case notice(NoticeRoomTimelineItem)
|
||||||
case redacted(RedactedRoomTimelineItem)
|
case redacted(RedactedRoomTimelineItem)
|
||||||
case encrypted(EncryptedRoomTimelineItem)
|
case encrypted(EncryptedRoomTimelineItem)
|
||||||
|
case backPaginationIndicator(Bool)
|
||||||
|
|
||||||
var id: String {
|
var id: String {
|
||||||
switch self {
|
switch self {
|
||||||
@@ -48,6 +49,8 @@ enum RoomTimelineViewProvider: Identifiable, Hashable {
|
|||||||
return item.id
|
return item.id
|
||||||
case .encrypted(let item):
|
case .encrypted(let item):
|
||||||
return item.id
|
return item.id
|
||||||
|
case .backPaginationIndicator:
|
||||||
|
return "BackpaginationLoadingIndicator"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,6 +76,10 @@ extension RoomTimelineViewProvider: View {
|
|||||||
RedactedRoomTimelineView(timelineItem: item)
|
RedactedRoomTimelineView(timelineItem: item)
|
||||||
case .encrypted(let item):
|
case .encrypted(let item):
|
||||||
EncryptedRoomTimelineView(timelineItem: item)
|
EncryptedRoomTimelineView(timelineItem: item)
|
||||||
|
case .backPaginationIndicator(let isBackPaginating):
|
||||||
|
ProgressView()
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.opacity(isBackPaginating ? 1.0 : 0.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user