mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
pr suggestions
This commit is contained in:
@@ -449,7 +449,7 @@ private extension RoomTimelineItemViewState {
|
|||||||
return [TimelineMediaPreviewItem.Media(roomTimelineItemViewState: self)].compactMap { $0 }
|
return [TimelineMediaPreviewItem.Media(roomTimelineItemViewState: self)].compactMap { $0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
return galleryItem.content.attachments(allowedTypes: allowedGalleryItemTypes).map {
|
return galleryItem.content.items(matching: allowedGalleryItemTypes).map {
|
||||||
TimelineMediaPreviewItem.Media(galleryParent: galleryItem, item: $0.item)
|
TimelineMediaPreviewItem.Media(galleryParent: galleryItem, item: $0.item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-17
@@ -20,14 +20,9 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
|
|||||||
|
|
||||||
private var isOldestItemVisible = false
|
private var isOldestItemVisible = false
|
||||||
|
|
||||||
/// The gallery attachment that a listed item was built from, keyed by that item's unique ID.
|
/// The gallery item that a listed item was built from, so that interactions can be forwarded
|
||||||
/// Interactions are forwarded using the gallery's own identifier, which is the one the timeline knows.
|
/// using the gallery's identifier rather than the listed item's.
|
||||||
private struct GalleryItemLocation {
|
private var galleryItemIDs = [TimelineItemIdentifier.UniqueID: GalleryItemID]()
|
||||||
let parentID: TimelineItemIdentifier
|
|
||||||
let mediaIndex: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
private var galleryItemLookup = [TimelineItemIdentifier.UniqueID: GalleryItemLocation]()
|
|
||||||
|
|
||||||
private var activeTimelineViewModel: TimelineViewModelProtocol {
|
private var activeTimelineViewModel: TimelineViewModelProtocol {
|
||||||
switch state.screenMode {
|
switch state.screenMode {
|
||||||
@@ -132,14 +127,14 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
|
|||||||
case .oldestItemDidDisappear:
|
case .oldestItemDidDisappear:
|
||||||
isOldestItemVisible = false
|
isOldestItemVisible = false
|
||||||
case .tappedItem(let item):
|
case .tappedItem(let item):
|
||||||
if let location = galleryItemLookup[item.id] {
|
if let galleryItemID = galleryItemIDs[item.id] {
|
||||||
activeTimelineViewModel.context.send(viewAction: .galleryItemTapped(itemID: location.parentID, index: location.mediaIndex))
|
activeTimelineViewModel.context.send(viewAction: .galleryItemTapped(galleryItemID))
|
||||||
} else {
|
} else {
|
||||||
activeTimelineViewModel.context.send(viewAction: .mediaTapped(itemID: item.identifier))
|
activeTimelineViewModel.context.send(viewAction: .mediaTapped(itemID: item.identifier))
|
||||||
}
|
}
|
||||||
case .longPressedItem(let item):
|
case .longPressedItem(let item):
|
||||||
// The menu acts on the gallery as a whole, as its actions can't apply to a single attachment.
|
// The menu acts on the gallery as a whole, as its actions can't apply to a single item.
|
||||||
let itemID = galleryItemLookup[item.id]?.parentID ?? item.identifier
|
let itemID = galleryItemIDs[item.id]?.timelineItemID ?? item.identifier
|
||||||
activeTimelineViewModel.context.send(viewAction: .displayTimelineItemMenu(itemID: itemID))
|
activeTimelineViewModel.context.send(viewAction: .displayTimelineItemMenu(itemID: itemID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,7 +187,7 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
|
|||||||
private func updateWithTimelineViewState(_ timelineViewState: TimelineViewState) {
|
private func updateWithTimelineViewState(_ timelineViewState: TimelineViewState) {
|
||||||
var newGroups = [MediaEventsTimelineGroup]()
|
var newGroups = [MediaEventsTimelineGroup]()
|
||||||
var currentItems = [RoomTimelineItemViewState]()
|
var currentItems = [RoomTimelineItemViewState]()
|
||||||
var newGalleryItemLookup = [TimelineItemIdentifier.UniqueID: GalleryItemLocation]()
|
var newGalleryItemIDs = [TimelineItemIdentifier.UniqueID: GalleryItemID]()
|
||||||
|
|
||||||
timelineViewState.timelineState.itemViewStates.flatMap { itemViewState -> [RoomTimelineItemViewState] in
|
timelineViewState.timelineState.itemViewStates.flatMap { itemViewState -> [RoomTimelineItemViewState] in
|
||||||
switch itemViewState.type {
|
switch itemViewState.type {
|
||||||
@@ -203,10 +198,9 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
|
|||||||
case .separator:
|
case .separator:
|
||||||
return [itemViewState]
|
return [itemViewState]
|
||||||
case .gallery(let galleryItem):
|
case .gallery(let galleryItem):
|
||||||
// A gallery's attachments are displayed flattened, listed individually.
|
|
||||||
let flattenedItems = galleryItem.itemsAsIndividualMessages(allowedTypes: timelineViewState.allowedGalleryItemTypes)
|
let flattenedItems = galleryItem.itemsAsIndividualMessages(allowedTypes: timelineViewState.allowedGalleryItemTypes)
|
||||||
for (mediaIndex, item) in flattenedItems {
|
for (mediaIndex, item) in flattenedItems {
|
||||||
newGalleryItemLookup[item.id.uniqueID] = .init(parentID: galleryItem.id, mediaIndex: mediaIndex)
|
newGalleryItemIDs[item.id.uniqueID] = .init(timelineItemID: galleryItem.id, mediaIndex: mediaIndex)
|
||||||
}
|
}
|
||||||
return flattenedItems.map { .init(item: $0.item, groupStyle: .single) }
|
return flattenedItems.map { .init(item: $0.item, groupStyle: .single) }
|
||||||
default:
|
default:
|
||||||
@@ -235,7 +229,7 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
|
|||||||
}
|
}
|
||||||
|
|
||||||
state.groups = newGroups
|
state.groups = newGroups
|
||||||
galleryItemLookup = newGalleryItemLookup
|
galleryItemIDs = newGalleryItemIDs
|
||||||
|
|
||||||
state.isBackPaginating = timelineViewState.timelineState.paginationState.backward == .paginating
|
state.isBackPaginating = timelineViewState.timelineState.paginationState.backward == .paginating
|
||||||
state.shouldShowEmptyState = newGroups.isEmpty && timelineViewState.timelineState.paginationState.backward == .endReached
|
state.shouldShowEmptyState = newGroups.isEmpty && timelineViewState.timelineState.paginationState.backward == .endReached
|
||||||
@@ -291,7 +285,7 @@ private extension GalleryRoomTimelineItem {
|
|||||||
func itemsAsIndividualMessages(allowedTypes: [TimelineAllowedGalleryItemType]?) -> [(mediaIndex: Int, item: EventBasedMessageTimelineItemProtocol)] {
|
func itemsAsIndividualMessages(allowedTypes: [TimelineAllowedGalleryItemType]?) -> [(mediaIndex: Int, item: EventBasedMessageTimelineItemProtocol)] {
|
||||||
guard let eventOrTransactionID = id.eventOrTransactionID else { return [] }
|
guard let eventOrTransactionID = id.eventOrTransactionID else { return [] }
|
||||||
|
|
||||||
return content.attachments(allowedTypes: allowedTypes).compactMap { mediaIndex, galleryItem in
|
return content.items(matching: allowedTypes).compactMap { mediaIndex, galleryItem in
|
||||||
let itemID = TimelineItemIdentifier.event(uniqueID: .init("\(id.uniqueID.value)-\(mediaIndex)"),
|
let itemID = TimelineItemIdentifier.event(uniqueID: .init("\(id.uniqueID.value)-\(mediaIndex)"),
|
||||||
eventOrTransactionID: eventOrTransactionID)
|
eventOrTransactionID: eventOrTransactionID)
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ enum TimelineViewAction {
|
|||||||
case itemDisappeared(itemID: TimelineItemIdentifier)
|
case itemDisappeared(itemID: TimelineItemIdentifier)
|
||||||
|
|
||||||
case mediaTapped(itemID: TimelineItemIdentifier)
|
case mediaTapped(itemID: TimelineItemIdentifier)
|
||||||
case galleryItemTapped(itemID: TimelineItemIdentifier, index: Int)
|
case galleryItemTapped(GalleryItemID)
|
||||||
case itemSendInfoTapped(itemID: TimelineItemIdentifier)
|
case itemSendInfoTapped(itemID: TimelineItemIdentifier)
|
||||||
case toggleReaction(key: String, itemID: TimelineItemIdentifier)
|
case toggleReaction(key: String, itemID: TimelineItemIdentifier)
|
||||||
case sendReadReceiptIfNeeded(TimelineItemIdentifier)
|
case sendReadReceiptIfNeeded(TimelineItemIdentifier)
|
||||||
|
|||||||
@@ -160,8 +160,8 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
|||||||
Task { await timelineController.processItemDisappearance(id) }
|
Task { await timelineController.processItemDisappearance(id) }
|
||||||
case .mediaTapped(let id):
|
case .mediaTapped(let id):
|
||||||
Task { await handleMediaTapped(with: id) }
|
Task { await handleMediaTapped(with: id) }
|
||||||
case .galleryItemTapped(let id, let index):
|
case .galleryItemTapped(let galleryItemID):
|
||||||
Task { await handleMediaTapped(with: id, galleryIndex: index) }
|
Task { await handleMediaTapped(with: galleryItemID.timelineItemID, galleryIndex: galleryItemID.mediaIndex) }
|
||||||
case .itemSendInfoTapped(let itemID):
|
case .itemSendInfoTapped(let itemID):
|
||||||
handleItemSendInfoTapped(itemID: itemID)
|
handleItemSendInfoTapped(itemID: itemID)
|
||||||
case .toggleReaction(let emoji, let itemID):
|
case .toggleReaction(let emoji, let itemID):
|
||||||
|
|||||||
+1
-1
@@ -61,7 +61,7 @@ struct GalleryRoomTimelineView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func tap(index: Int) {
|
private func tap(index: Int) {
|
||||||
context?.send(viewAction: .galleryItemTapped(itemID: timelineItem.id, index: index))
|
context?.send(viewAction: .galleryItemTapped(.init(timelineItemID: timelineItem.id, mediaIndex: index)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -16,11 +16,10 @@ nonisolated struct GalleryRoomTimelineItemContent: Hashable {
|
|||||||
var formattedCaptionHTMLString: String?
|
var formattedCaptionHTMLString: String?
|
||||||
let items: [GalleryItem]
|
let items: [GalleryItem]
|
||||||
|
|
||||||
/// The attachments of the given types, paired with their position in the gallery so that they remain
|
/// The items of the given types, paired with their position in the gallery so that they remain
|
||||||
/// identifiable once separated from it. Attachments of an unknown type are never included as there's
|
/// identifiable once separated from it. Items of an unknown type are never included.
|
||||||
/// nothing to show for them.
|
|
||||||
/// - Parameter allowedTypes: The types to include, or `nil` to include them all.
|
/// - Parameter allowedTypes: The types to include, or `nil` to include them all.
|
||||||
func attachments(allowedTypes: [TimelineAllowedGalleryItemType]?) -> [(mediaIndex: Int, item: GalleryItem)] {
|
func items(matching allowedTypes: [TimelineAllowedGalleryItemType]?) -> [(mediaIndex: Int, item: GalleryItem)] {
|
||||||
items.enumerated().compactMap { mediaIndex, item in
|
items.enumerated().compactMap { mediaIndex, item in
|
||||||
guard let allowedItemType = item.allowedItemType,
|
guard let allowedItemType = item.allowedItemType,
|
||||||
allowedTypes?.contains(allowedItemType) ?? true else {
|
allowedTypes?.contains(allowedItemType) ?? true else {
|
||||||
|
|||||||
Reference in New Issue
Block a user