mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Allow previews in the timeline to include filtered galleries (#5943)
* remove the usage of the timeline kind override in favour of getting it properly from the timeline view model * allow the previews to include gallery items filtered by the allowed types when started outside the gallery sss asa * fix for actions not being forwarded to the timeline right * pr suggestions
This commit is contained in:
@@ -35,13 +35,19 @@ class TimelineMediaPreviewDataSource: NSObject, QLPreviewControllerDataSource {
|
||||
|
||||
var paginationState: TimelinePaginationState
|
||||
|
||||
/// The gallery attachments to include, so that a gallery only contributes the media being browsed.
|
||||
private let allowedGalleryItemTypes: [TimelineAllowedGalleryItemType]?
|
||||
|
||||
/// Builds a data source spanning every previewable attachment in the timeline, paginating
|
||||
/// as the user swipes past the loaded range. Used when tapping a standalone media message.
|
||||
init(itemViewStates: [RoomTimelineItemViewState],
|
||||
initialItem: EventBasedMessageTimelineItemProtocol,
|
||||
initialPadding: Int = 100,
|
||||
paginationState: TimelinePaginationState) {
|
||||
previewItems = itemViewStates.compactMap(TimelineMediaPreviewItem.Media.init)
|
||||
paginationState: TimelinePaginationState,
|
||||
allowedGalleryItemTypes: [TimelineAllowedGalleryItemType]? = nil) {
|
||||
self.allowedGalleryItemTypes = allowedGalleryItemTypes
|
||||
|
||||
previewItems = itemViewStates.flatMap { $0.previewableMedia(allowedGalleryItemTypes: allowedGalleryItemTypes) }
|
||||
|
||||
let initialPreviewID = TimelineMediaPreviewItem.Media(timelineItem: initialItem).id
|
||||
if let initialItemArrayIndex = previewItems.firstIndex(where: { $0.id == initialPreviewID }) {
|
||||
@@ -66,6 +72,8 @@ class TimelineMediaPreviewDataSource: NSObject, QLPreviewControllerDataSource {
|
||||
/// gallery and there's no timeline pagination to drive.
|
||||
init(galleryItem: GalleryRoomTimelineItem,
|
||||
initialIndex: Int) {
|
||||
allowedGalleryItemTypes = nil // All of the gallery's attachments are shown.
|
||||
|
||||
let media = galleryItem.content.items.map { item in
|
||||
TimelineMediaPreviewItem.Media(galleryParent: galleryItem, item: item)
|
||||
}
|
||||
@@ -93,17 +101,17 @@ class TimelineMediaPreviewDataSource: NSObject, QLPreviewControllerDataSource {
|
||||
}
|
||||
|
||||
func updatePreviewItems(itemViewStates: [RoomTimelineItemViewState]) {
|
||||
let newItems: [TimelineMediaPreviewItem.Media] = itemViewStates.compactMap { itemViewState in
|
||||
guard let newItem = TimelineMediaPreviewItem.Media(roomTimelineItemViewState: itemViewState) else { return nil }
|
||||
|
||||
// If an item already exists use that instead to preserve the file handle, download error etc.
|
||||
if let oldItem = previewItems.first(where: { $0.id == newItem.id }) {
|
||||
oldItem.content = newItem.content
|
||||
return oldItem
|
||||
let newItems: [TimelineMediaPreviewItem.Media] = itemViewStates
|
||||
.flatMap { $0.previewableMedia(allowedGalleryItemTypes: allowedGalleryItemTypes) }
|
||||
.map { newItem in
|
||||
// If an item already exists use that instead to preserve the file handle, download error etc.
|
||||
if let oldItem = previewItems.first(where: { $0.id == newItem.id }) {
|
||||
oldItem.content = newItem.content
|
||||
return oldItem
|
||||
}
|
||||
|
||||
return newItem
|
||||
}
|
||||
|
||||
return newItem
|
||||
}
|
||||
|
||||
var hasPaginated = false
|
||||
if let range = newItems.map(\.id).firstRange(of: previewItems.map(\.id)) {
|
||||
@@ -430,3 +438,23 @@ enum TimelineMediaPreviewItem: Equatable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension RoomTimelineItemViewState {
|
||||
/// The media of this item that can be previewed, flattening a gallery message into its individual
|
||||
/// attachments so that they can be browsed alongside the timeline's other media.
|
||||
/// - Parameter allowedGalleryItemTypes: Restricts a gallery's attachments to the media being
|
||||
/// browsed, as the SDK can only filter the gallery event as a whole.
|
||||
func previewableMedia(allowedGalleryItemTypes: [TimelineAllowedGalleryItemType]?) -> [TimelineMediaPreviewItem.Media] {
|
||||
guard case .gallery(let galleryItem) = type else {
|
||||
return [TimelineMediaPreviewItem.Media(roomTimelineItemViewState: self)].compactMap { $0 }
|
||||
}
|
||||
|
||||
return galleryItem.content.items.filter { item in
|
||||
guard let allowedItemType = item.allowedItemType else {
|
||||
return false // Nothing to preview, and unlike a tile there's no index to line up with.
|
||||
}
|
||||
|
||||
return allowedGalleryItemTypes?.contains(allowedItemType) ?? true
|
||||
}.map { TimelineMediaPreviewItem.Media(galleryParent: galleryItem, item: $0) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,6 @@ class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType {
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private let appMediator: AppMediatorProtocol
|
||||
|
||||
/// Overrides the timeline kind used to build the context menu. Gallery previews use `.media` so the
|
||||
/// standard download/forward/delete actions appear, since their underlying room timeline is `.live`.
|
||||
private let menuTimelineKind: TimelineKind?
|
||||
|
||||
private var contentScannerService: ContentScannerServiceProtocol? {
|
||||
timelineViewModel.context.contentScannerService
|
||||
}
|
||||
@@ -47,13 +43,13 @@ class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType {
|
||||
self.photoLibraryManager = photoLibraryManager
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.appMediator = appMediator
|
||||
menuTimelineKind = nil
|
||||
|
||||
let timelineState = timelineViewModel.context.viewState.timelineState
|
||||
|
||||
super.init(initialViewState: TimelineMediaPreviewViewState(dataSource: .init(itemViewStates: timelineState.itemViewStates,
|
||||
initialItem: initialItem,
|
||||
paginationState: timelineState.paginationState)),
|
||||
paginationState: timelineState.paginationState,
|
||||
allowedGalleryItemTypes: timelineViewModel.context.viewState.allowedGalleryItemTypes)),
|
||||
mediaProvider: mediaProvider)
|
||||
|
||||
rebuildCurrentItemActions()
|
||||
@@ -99,7 +95,6 @@ class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType {
|
||||
self.photoLibraryManager = photoLibraryManager
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.appMediator = appMediator
|
||||
menuTimelineKind = .media(.roomScreenLive)
|
||||
|
||||
super.init(initialViewState: TimelineMediaPreviewViewState(dataSource: .init(galleryItem: galleryItem,
|
||||
initialIndex: initialIndex)),
|
||||
@@ -236,7 +231,7 @@ class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType {
|
||||
pinnedEventIDs: timelineContext.viewState.pinnedEventIDs,
|
||||
isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled,
|
||||
areThreadsEnabled: timelineContext.viewState.areThreadsEnabled,
|
||||
timelineKind: menuTimelineKind ?? timelineContext.viewState.timelineKind,
|
||||
timelineKind: timelineContext.viewState.timelineKind,
|
||||
emojiProvider: timelineContext.viewState.emojiProvider)
|
||||
.makeActions()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user