From a292c41ca5ef6aec602bd2fd15da45dbd6aaca79 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Wed, 27 Nov 2024 06:30:10 +0000 Subject: [PATCH] Move the media caption composer (and Add Caption action) behind a feature flag for now. (#3560) --- ElementX/Sources/Application/AppSettings.swift | 4 ++++ .../FlowCoordinators/RoomFlowCoordinator.swift | 3 ++- .../MediaUploadPreviewScreenCoordinator.swift | 4 +++- .../MediaUploadPreviewScreenModels.swift | 1 + .../MediaUploadPreviewScreenViewModel.swift | 5 +++-- .../View/MediaUploadPreviewScreen.swift | 13 ++++++++----- .../View/PinnedEventsTimelineScreen.swift | 1 + .../Screens/RoomScreen/View/RoomScreen.swift | 1 + .../DeveloperOptionsScreenModels.swift | 1 + .../View/DeveloperOptionsScreen.swift | 4 ++++ .../Sources/Screens/Timeline/TimelineModels.swift | 1 + .../Screens/Timeline/TimelineViewModel.swift | 5 +++++ .../ItemMenu/TimelineItemMenuActionProvider.swift | 3 ++- .../View/Style/TimelineItemBubbledStylerView.swift | 1 + .../MediaUploadPreviewScreenViewModelTests.swift | 3 ++- 15 files changed, 39 insertions(+), 11 deletions(-) diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index cb800e96a..eff6e295a 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -47,6 +47,7 @@ final class AppSettings { case fuzzyRoomListSearchEnabled case enableOnlySignedDeviceIsolationMode case knockingEnabled + case createMediaCaptionsEnabled } private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier @@ -280,6 +281,9 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.knockingEnabled, defaultValue: false, storageType: .userDefaults(store)) var knockingEnabled + @UserPreference(key: UserDefaultsKeys.createMediaCaptionsEnabled, defaultValue: false, storageType: .userDefaults(store)) + var createMediaCaptionsEnabled + #endif // MARK: - Shared diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index b25c076bf..3a58bdfac 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -996,7 +996,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { roomProxy: roomProxy, mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: appSettings), title: url.lastPathComponent, - url: url) + url: url, + createMediaCaptionsEnabled: appSettings.createMediaCaptionsEnabled) let mediaUploadPreviewScreenCoordinator = MediaUploadPreviewScreenCoordinator(parameters: parameters) diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift index 42633e9b5..78bf65104 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift @@ -14,6 +14,7 @@ struct MediaUploadPreviewScreenCoordinatorParameters { let mediaUploadingPreprocessor: MediaUploadingPreprocessor let title: String? let url: URL + let createMediaCaptionsEnabled: Bool } enum MediaUploadPreviewScreenCoordinatorAction { @@ -34,7 +35,8 @@ final class MediaUploadPreviewScreenCoordinator: CoordinatorProtocol { roomProxy: parameters.roomProxy, mediaUploadingPreprocessor: parameters.mediaUploadingPreprocessor, title: parameters.title, - url: parameters.url) + url: parameters.url, + createMediaCaptionsEnabled: parameters.createMediaCaptionsEnabled) } func start() { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift index f9c1eb178..ecd05d345 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift @@ -14,6 +14,7 @@ enum MediaUploadPreviewScreenViewModelAction { struct MediaUploadPreviewScreenViewState: BindableState { let url: URL let title: String? + let showMediaCaptionComposer: Bool var shouldDisableInteraction = false var bindings = MediaUploadPreviewScreenBindings() diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift index c7f2164db..e4d8decd4 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift @@ -32,13 +32,14 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, roomProxy: JoinedRoomProxyProtocol, mediaUploadingPreprocessor: MediaUploadingPreprocessor, title: String?, - url: URL) { + url: URL, + createMediaCaptionsEnabled: Bool) { self.userIndicatorController = userIndicatorController self.roomProxy = roomProxy self.mediaUploadingPreprocessor = mediaUploadingPreprocessor self.url = url - super.init(initialViewState: MediaUploadPreviewScreenViewState(url: url, title: title)) + super.init(initialViewState: MediaUploadPreviewScreenViewState(url: url, title: title, showMediaCaptionComposer: createMediaCaptionsEnabled)) } override func process(viewAction: MediaUploadPreviewScreenViewAction) { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift index bcd0309b6..807df6993 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift @@ -22,10 +22,12 @@ struct MediaUploadPreviewScreen: View { .id(context.viewState.url) .ignoresSafeArea(edges: [.horizontal]) .safeAreaInset(edge: .bottom, spacing: 0) { - composer - .padding(.horizontal, 12) - .padding(.vertical, 16) - .background() // Don't use compound so we match the QLPreviewController. + if context.viewState.showMediaCaptionComposer { + composer + .padding(.horizontal, 12) + .padding(.vertical, 16) + .background() // Don't use compound so we match the QLPreviewController. + } } .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) @@ -156,7 +158,8 @@ struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview { roomProxy: JoinedRoomProxyMock(), mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), title: "App Icon.png", - url: snapshotURL) + url: snapshotURL, + createMediaCaptionsEnabled: true) static var previews: some View { NavigationStack { MediaUploadPreviewScreen(context: viewModel.context) diff --git a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift index 8a18ec274..80dcd267c 100644 --- a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift +++ b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift @@ -37,6 +37,7 @@ struct PinnedEventsTimelineScreen: View { pinnedEventIDs: timelineContext.viewState.pinnedEventIDs, isDM: timelineContext.viewState.isEncryptedOneToOneRoom, isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled, + isCreateMediaCaptionsEnabled: timelineContext.viewState.isCreateMediaCaptionsEnabled, isPinnedEventsTimeline: timelineContext.viewState.isPinnedEventsTimeline, emojiProvider: timelineContext.viewState.emojiProvider) .makeActions() diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index aad279595..c6f179225 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -75,6 +75,7 @@ struct RoomScreen: View { pinnedEventIDs: timelineContext.viewState.pinnedEventIDs, isDM: timelineContext.viewState.isEncryptedOneToOneRoom, isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled, + isCreateMediaCaptionsEnabled: timelineContext.viewState.isCreateMediaCaptionsEnabled, isPinnedEventsTimeline: timelineContext.viewState.isPinnedEventsTimeline, emojiProvider: timelineContext.viewState.emojiProvider) .makeActions() diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift index 2f1322ecc..d8a496c8f 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift @@ -50,6 +50,7 @@ protocol DeveloperOptionsProtocol: AnyObject { var enableOnlySignedDeviceIsolationMode: Bool { get set } var elementCallBaseURLOverride: URL? { get set } var knockingEnabled: Bool { get set } + var createMediaCaptionsEnabled: Bool { get set } } extension AppSettings: DeveloperOptionsProtocol { } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift index bdeb01df7..de6909cc5 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -53,6 +53,10 @@ struct DeveloperOptionsScreen: View { Toggle(isOn: $context.hideTimelineMedia) { Text("Hide image & video previews") } + + Toggle(isOn: $context.createMediaCaptionsEnabled) { + Text("Allow creation of media captions") + } } Section("Join rules") { diff --git a/ElementX/Sources/Screens/Timeline/TimelineModels.swift b/ElementX/Sources/Screens/Timeline/TimelineModels.swift index 8e8bc71fc..2108e635a 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineModels.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineModels.swift @@ -99,6 +99,7 @@ struct TimelineViewState: BindableState { var canCurrentUserRedactSelf = false var canCurrentUserPin = false var isViewSourceEnabled: Bool + var isCreateMediaCaptionsEnabled: Bool var hideTimelineMedia: Bool // The `pinnedEventIDs` are used only to determine if an item is already pinned or not. diff --git a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift index 66ce90d75..3777feed1 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift @@ -81,6 +81,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { timelineViewState: TimelineState(focussedEvent: focussedEventID.map { .init(eventID: $0, appearance: .immediate) }), ownUserID: roomProxy.ownUserID, isViewSourceEnabled: appSettings.viewSourceEnabled, + isCreateMediaCaptionsEnabled: appSettings.createMediaCaptionsEnabled, hideTimelineMedia: appSettings.hideTimelineMedia, pinnedEventIDs: roomProxy.infoPublisher.value.pinnedEventIDs, bindings: .init(reactionsCollapsed: [:]), @@ -447,6 +448,10 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { .weakAssign(to: \.state.isViewSourceEnabled, on: self) .store(in: &cancellables) + appSettings.$createMediaCaptionsEnabled + .weakAssign(to: \.state.isCreateMediaCaptionsEnabled, on: self) + .store(in: &cancellables) + appSettings.$hideTimelineMedia .weakAssign(to: \.state.hideTimelineMedia, on: self) .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift index df7422143..cad18009e 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift @@ -16,6 +16,7 @@ struct TimelineItemMenuActionProvider { let pinnedEventIDs: Set let isDM: Bool let isViewSourceEnabled: Bool + let isCreateMediaCaptionsEnabled: Bool let isPinnedEventsTimeline: Bool let emojiProvider: EmojiProviderProtocol @@ -68,7 +69,7 @@ struct TimelineItemMenuActionProvider { if let messageItem = item as? EventBasedMessageTimelineItemProtocol, messageItem.supportsMediaCaption { if messageItem.hasMediaCaption { actions.append(contentsOf: [.editCaption, .removeCaption]) - } else { + } else if isCreateMediaCaptionsEnabled { actions.append(.addCaption) } } else if !(item is VoiceMessageRoomTimelineItem) { diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift index a99fdf1fa..037f7f182 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift @@ -143,6 +143,7 @@ struct TimelineItemBubbledStylerView: View { pinnedEventIDs: context.viewState.pinnedEventIDs, isDM: context.viewState.isEncryptedOneToOneRoom, isViewSourceEnabled: context.viewState.isViewSourceEnabled, + isCreateMediaCaptionsEnabled: context.viewState.isCreateMediaCaptionsEnabled, isPinnedEventsTimeline: context.viewState.isPinnedEventsTimeline, emojiProvider: context.viewState.emojiProvider) TimelineItemMacContextMenu(item: timelineItem, actionProvider: provider) { action in diff --git a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift index c74ec0318..9a47185ae 100644 --- a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift +++ b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift @@ -125,7 +125,8 @@ class MediaUploadPreviewScreenViewModelTests: XCTestCase { roomProxy: roomProxy, mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), title: "Some File", - url: url) + url: url, + createMediaCaptionsEnabled: true) } private func verifyCaption(_ caption: String?, expectedCaption: String?) -> Result {