Add developer option to hide media in the timeline. (#3366)

This commit is contained in:
Doug
2024-10-03 17:59:39 +01:00
committed by GitHub
parent 4f29821306
commit e6f4dd33a0
24 changed files with 325 additions and 65 deletions
@@ -97,6 +97,7 @@ struct TimelineViewState: BindableState {
var canCurrentUserRedactSelf = false
var canCurrentUserPin = false
var isViewSourceEnabled: Bool
var hideTimelineMedia: 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
@@ -125,6 +125,13 @@ class TimelineTableViewController: UIViewController {
}
}
var hideTimelineMedia = false {
didSet {
guard let snapshot = dataSource?.snapshot() else { return }
dataSource?.applySnapshotUsingReloadData(snapshot)
}
}
/// Used to hold an observable object that the typing indicator can use
let typingMembers = TypingMembersObservableObject(members: [])
@@ -260,21 +267,19 @@ class TimelineTableViewController: UIViewController {
let cell = tableView.dequeueReusableCell(withIdentifier: TimelineItemCell.reuseIdentifier, for: indexPath)
guard let self, let cell = cell as? TimelineItemCell else { return cell }
// A local reference to avoid capturing self in the cell configuration.
let coordinator = self.coordinator
let viewState = timelineItemsDictionary[id]
cell.item = viewState
guard let viewState else {
return cell
}
cell.contentConfiguration = UIHostingConfiguration {
cell.contentConfiguration = UIHostingConfiguration { [coordinator, hideTimelineMedia] in
RoomTimelineItemView(viewState: viewState)
.id(id)
.frame(maxWidth: .infinity, alignment: .leading)
.environmentObject(coordinator.context) // Attempted fix at a crash in TimelineItemContextMenu
.environment(\.timelineContext, coordinator.context)
.environment(\.shouldAutomaticallyLoadImages, !hideTimelineMedia)
}
.margins(.all, 0) // Margins are handled in the stylers
.minSize(height: 1)
@@ -78,6 +78,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
timelineViewState: TimelineState(focussedEvent: focussedEventID.map { .init(eventID: $0, appearance: .immediate) }),
ownUserID: roomProxy.ownUserID,
isViewSourceEnabled: appSettings.viewSourceEnabled,
hideTimelineMedia: appSettings.hideTimelineMedia,
bindings: .init(reactionsCollapsed: [:])),
mediaProvider: mediaProvider)
@@ -440,6 +441,10 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
appSettings.$viewSourceEnabled
.weakAssign(to: \.state.isViewSourceEnabled, on: self)
.store(in: &cancellables)
appSettings.$hideTimelineMedia
.weakAssign(to: \.state.hideTimelineMedia, on: self)
.store(in: &cancellables)
}
private func updatePinnedEventIDs() async {
@@ -15,6 +15,7 @@ struct ImageRoomTimelineView: View {
var body: some View {
TimelineStyler(timelineItem: timelineItem) {
LoadableImage(mediaSource: source,
mediaType: .timelineItem,
blurhash: timelineItem.content.blurhash,
mediaProvider: context.mediaProvider) {
placeholder
@@ -35,14 +36,9 @@ struct ImageRoomTimelineView: View {
}
var placeholder: some View {
ZStack {
Rectangle()
.foregroundColor(timelineItem.isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming)
.opacity(0.3)
ProgressView(L10n.commonLoading)
.frame(maxWidth: .infinity)
}
Rectangle()
.foregroundColor(timelineItem.isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming)
.opacity(0.3)
}
}
@@ -15,6 +15,7 @@ struct StickerRoomTimelineView: View {
var body: some View {
TimelineStyler(timelineItem: timelineItem) {
LoadableImage(url: timelineItem.imageURL,
mediaType: .timelineItem,
blurhash: timelineItem.blurhash,
mediaProvider: context.mediaProvider) {
placeholder
@@ -27,14 +28,9 @@ struct StickerRoomTimelineView: View {
}
private var placeholder: some View {
ZStack {
Rectangle()
.foregroundColor(timelineItem.isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming)
.opacity(0.3)
ProgressView(L10n.commonLoading)
.frame(maxWidth: .infinity)
}
Rectangle()
.foregroundColor(timelineItem.isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming)
.opacity(0.3)
}
}
@@ -26,6 +26,7 @@ struct VideoRoomTimelineView: View {
var thumbnail: some View {
if let thumbnailSource = timelineItem.content.thumbnailSource {
LoadableImage(mediaSource: thumbnailSource,
mediaType: .timelineItem,
blurhash: timelineItem.content.blurhash,
mediaProvider: context.mediaProvider) { imageView in
imageView
@@ -47,14 +48,9 @@ struct VideoRoomTimelineView: View {
}
var placeholder: some View {
ZStack {
Rectangle()
.foregroundColor(timelineItem.isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming)
.opacity(0.3)
ProgressView(L10n.commonLoading)
.frame(maxWidth: .infinity)
}
Rectangle()
.foregroundColor(timelineItem.isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming)
.opacity(0.3)
}
}
@@ -60,6 +60,9 @@ struct TimelineView: UIViewControllerRepresentable {
if tableViewController.focussedEvent != context.viewState.timelineViewState.focussedEvent {
tableViewController.focussedEvent = context.viewState.timelineViewState.focussedEvent
}
if tableViewController.hideTimelineMedia != context.viewState.hideTimelineMedia {
tableViewController.hideTimelineMedia = context.viewState.hideTimelineMedia
}
if tableViewController.typingMembers.members != context.viewState.typingMembers {
tableViewController.setTypingMembers(context.viewState.typingMembers)