mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Add developer option to hide media in the timeline. (#3366)
This commit is contained in:
@@ -91,7 +91,7 @@ struct RoomPollsHistoryScreen: View {
|
||||
Button {
|
||||
context.send(viewAction: .loadMore)
|
||||
} label: {
|
||||
Text(L10n.Action.loadMore)
|
||||
Text(L10n.actionLoadMore)
|
||||
.font(.compound.bodyLGSemibold)
|
||||
.padding(.horizontal, 12)
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ struct RoomScreen: View {
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
.environmentObject(timelineContext)
|
||||
.environment(\.timelineContext, timelineContext)
|
||||
// Make sure the reply header honours the hideTimelineMedia setting too.
|
||||
.environment(\.shouldAutomaticallyLoadImages, !timelineContext.viewState.hideTimelineMedia)
|
||||
}
|
||||
.overlay(alignment: .top) {
|
||||
Group {
|
||||
|
||||
+2
-1
@@ -44,9 +44,10 @@ protocol DeveloperOptionsProtocol: AnyObject {
|
||||
var logLevel: TracingConfiguration.LogLevel { get set }
|
||||
var slidingSyncDiscovery: AppSettings.SlidingSyncDiscovery { get set }
|
||||
var hideUnreadMessagesBadge: Bool { get set }
|
||||
var elementCallBaseURLOverride: URL? { get set }
|
||||
var fuzzyRoomListSearchEnabled: Bool { get set }
|
||||
var hideTimelineMedia: Bool { get set }
|
||||
var enableOnlySignedDeviceIsolationMode: Bool { get set }
|
||||
var elementCallBaseURLOverride: URL? { get set }
|
||||
}
|
||||
|
||||
extension AppSettings: DeveloperOptionsProtocol { }
|
||||
|
||||
+6
@@ -45,6 +45,12 @@ struct DeveloperOptionsScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
Section("Timeline") {
|
||||
Toggle(isOn: $context.hideTimelineMedia) {
|
||||
Text("Hide image & video previews")
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
Toggle(isOn: $context.enableOnlySignedDeviceIsolationMode) {
|
||||
Text("Exclude not secure devices when sending/receiving messages")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+4
-8
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-8
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-8
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user