diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Contents.json index ead86edbb..04b38da3e 100644 --- a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Contents.json @@ -1,17 +1,17 @@ { "images" : [ { - "filename" : "action_voice_message.png", + "filename" : "Microphone icon.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "action_voice_message@2x.png", + "filename" : "Microphone icon@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "action_voice_message@3x.png", + "filename" : "Microphone icon@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon.png new file mode 100644 index 000000000..8a6b3eb14 Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon.png differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon@2x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon@2x.png new file mode 100644 index 000000000..5b404b74c Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon@2x.png differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon@3x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon@3x.png new file mode 100644 index 000000000..520e22e94 Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/Microphone icon@3x.png differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message.png deleted file mode 100644 index b969cb3aa..000000000 Binary files a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message.png and /dev/null differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message@2x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message@2x.png deleted file mode 100644 index 32c6236a6..000000000 Binary files a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message@2x.png and /dev/null differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message@3x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message@3x.png deleted file mode 100644 index e8cc54c29..000000000 Binary files a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_default.imageset/action_voice_message@3x.png and /dev/null differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Contents.json index 900874ca1..bc412b2cf 100644 --- a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Contents.json @@ -1,17 +1,17 @@ { "images" : [ { - "filename" : "voice_message_record_button_recording.png", + "filename" : "Microphone asset.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "voice_message_record_button_recording@2x.png", + "filename" : "Microphone asset@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "voice_message_record_button_recording@3x.png", + "filename" : "Microphone asset@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset.png new file mode 100644 index 000000000..ffeb00aaf Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset.png differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset@2x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset@2x.png new file mode 100644 index 000000000..8582e2d23 Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset@2x.png differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset@3x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset@3x.png new file mode 100644 index 000000000..e48d9a36b Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/Microphone asset@3x.png differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording.png deleted file mode 100644 index 5972e1272..000000000 Binary files a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording.png and /dev/null differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording@2x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording@2x.png deleted file mode 100644 index 802268ba0..000000000 Binary files a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording@2x.png and /dev/null differ diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording@3x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording@3x.png deleted file mode 100644 index b1def35e1..000000000 Binary files a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_record_button_recording.imageset/voice_message_record_button_recording@3x.png and /dev/null differ diff --git a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift index 49f496dbd..95c5c4a02 100644 --- a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift +++ b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift @@ -32,6 +32,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp // MARK: - Properties // MARK: Private + private var voiceMessageToolbarView: VoiceMessageToolbarView? private var cancellables = Set() private var heightConstraint: NSLayoutConstraint! private var hostingViewController: VectorHostingController! @@ -39,42 +40,6 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp private var viewModel: ComposerViewModelProtocol = ComposerViewModel(initialViewState: ComposerViewState()) // MARK: Public - var isEncryptionEnabled = false { - didSet { - updatePlaceholderText() - } - } - - /// The current html content of the composer - var htmlContent: String { - get { - wysiwygViewModel.content.html - } - set { - wysiwygViewModel.setHtmlContent(newValue) - } - } - - /// The display name to show when in edit/reply - var eventSenderDisplayName: String! { - get { - viewModel.eventSenderDisplayName - } - set { - viewModel.eventSenderDisplayName = newValue - } - } - - /// Whether the composer is in send, reply or edit mode. - var sendMode: RoomInputToolbarViewSendMode { - get { - viewModel.sendMode.legacySendMode - } - set { - viewModel.sendMode = ComposerSendMode(from: newValue) - updatePlaceholderText() - } - } override var placeholder: String! { get { @@ -169,9 +134,22 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp switch result { case .cancel: self.toolbarViewDelegate?.roomInputToolbarViewDidTapCancel(self) + case let .contentDidChange(isEmpty): + setVoiceMessageToolbarIsHidden(!isEmpty) } } + private func setVoiceMessageToolbarIsHidden(_ isHidden: Bool) { + guard let voiceMessageToolbarView = voiceMessageToolbarView else { return } + UIView.transition( + with: voiceMessageToolbarView, duration: 0.15, + options: .transitionCrossDissolve, + animations: { + voiceMessageToolbarView.isHidden = isHidden + } + ) + } + private func registerThemeServiceDidChangeThemeNotification() { NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) } @@ -185,12 +163,64 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp wysiwygViewModel.textColor = theme.colors.primaryContent } - // MARK: - RoomInputToolbarViewProtocol + // MARK: - HtmlRoomInputToolbarViewProtocol + var isEncryptionEnabled = false { + didSet { + updatePlaceholderText() + } + } + + /// The current html content of the composer + var htmlContent: String { + get { + wysiwygViewModel.content.html + } + set { + wysiwygViewModel.setHtmlContent(newValue) + } + } + + /// The display name to show when in edit/reply + var eventSenderDisplayName: String! { + get { + viewModel.eventSenderDisplayName + } + set { + viewModel.eventSenderDisplayName = newValue + } + } + + /// Whether the composer is in send, reply or edit mode. + var sendMode: RoomInputToolbarViewSendMode { + get { + viewModel.sendMode.legacySendMode + } + set { + viewModel.sendMode = ComposerSendMode(from: newValue) + updatePlaceholderText() + } + } /// Add the voice message toolbar to the composer /// - Parameter voiceMessageToolbarView: the voice message toolbar UIView func setVoiceMessageToolbarView(_ voiceMessageToolbarView: UIView!) { - // TODO embed the voice messages UI + if let voiceMessageToolbarView = voiceMessageToolbarView as? VoiceMessageToolbarView { + self.voiceMessageToolbarView = voiceMessageToolbarView + voiceMessageToolbarView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.deactivate(voiceMessageToolbarView.containersTopConstraints) + addSubview(voiceMessageToolbarView) + NSLayoutConstraint.activate( + [ + hostingViewController.view.topAnchor.constraint(equalTo: voiceMessageToolbarView.topAnchor), + hostingViewController.view.leftAnchor.constraint(equalTo: voiceMessageToolbarView.leftAnchor), + hostingViewController.view.bottomAnchor.constraint(equalTo: voiceMessageToolbarView.bottomAnchor, constant: 4), + hostingViewController.view.rightAnchor.constraint(equalTo: voiceMessageToolbarView.rightAnchor) + ] + ) + } else { + self.voiceMessageToolbarView?.removeFromSuperview() + self.voiceMessageToolbarView = nil + } } func toolbarHeight() -> CGFloat { diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift index a5e634dfd..b78d1df76 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift @@ -88,6 +88,8 @@ class VoiceMessageToolbarView: PassthroughView, NibLoadable, Themable, UIGesture @IBOutlet private var toastNotificationContainerView: UIView! @IBOutlet private var toastNotificationLabel: UILabel! + @IBOutlet var containersTopConstraints: [NSLayoutConstraint]! + private var playbackView: VoiceMessagePlaybackView! private var cancelLabelToRecordButtonDistance: CGFloat = 0.0 diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.xib b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.xib index 52dcce870..a5cb9a5b8 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.xib +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.xib @@ -1,16 +1,16 @@ - + - + - + @@ -19,7 +19,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -267,12 +267,14 @@ + + - + diff --git a/RiotSwiftUI/Modules/Room/Composer/MockComposerScreenState.swift b/RiotSwiftUI/Modules/Room/Composer/MockComposerScreenState.swift index 4aa483785..48d7df054 100644 --- a/RiotSwiftUI/Modules/Room/Composer/MockComposerScreenState.swift +++ b/RiotSwiftUI/Modules/Room/Composer/MockComposerScreenState.swift @@ -40,11 +40,13 @@ enum MockComposerScreenState: MockScreenState, CaseIterable { viewModel.callback = { [weak viewModel, weak wysiwygviewModel] result in guard let viewModel = viewModel else { return } - if viewModel.sendMode == .edit { - wysiwygviewModel?.setHtmlContent("") - } switch result { - case .cancel: viewModel.sendMode = .send + case .cancel: + if viewModel.sendMode == .edit { + wysiwygviewModel?.setHtmlContent("") + } + viewModel.sendMode = .send + default: break } } diff --git a/RiotSwiftUI/Modules/Room/Composer/Model/ComposerModels.swift b/RiotSwiftUI/Modules/Room/Composer/Model/ComposerModels.swift index 00470aa53..badcd2b20 100644 --- a/RiotSwiftUI/Modules/Room/Composer/Model/ComposerModels.swift +++ b/RiotSwiftUI/Modules/Room/Composer/Model/ComposerModels.swift @@ -127,12 +127,14 @@ enum ComposerSendMode: Equatable { case createDM } -enum ComposerViewAction { +enum ComposerViewAction: Equatable { case cancel + case contentDidChange(isEmpty: Bool) } -enum ComposerViewModelResult { +enum ComposerViewModelResult: Equatable { case cancel + case contentDidChange(isEmpty: Bool) } diff --git a/RiotSwiftUI/Modules/Room/Composer/Test/UI/ComposerUITests.swift b/RiotSwiftUI/Modules/Room/Composer/Test/UI/ComposerUITests.swift index 1a37c020b..08ce71fc0 100644 --- a/RiotSwiftUI/Modules/Room/Composer/Test/UI/ComposerUITests.swift +++ b/RiotSwiftUI/Modules/Room/Composer/Test/UI/ComposerUITests.swift @@ -25,11 +25,10 @@ final class ComposerUITests: MockScreenTestCase { let wysiwygTextView = app.textViews.allElementsBoundByIndex[0] XCTAssertTrue(wysiwygTextView.exists) let sendButton = app.buttons["sendButton"] - XCTAssertTrue(sendButton.exists) - XCTAssertFalse(sendButton.isEnabled) + XCTAssertFalse(sendButton.exists) wysiwygTextView.tap() wysiwygTextView.typeText("test") - XCTAssertTrue(sendButton.isEnabled) + XCTAssertTrue(sendButton.exists) XCTAssertFalse(app.buttons["editButton"].exists) } @@ -39,8 +38,7 @@ final class ComposerUITests: MockScreenTestCase { let wysiwygTextView = app.textViews.allElementsBoundByIndex[0] XCTAssertTrue(wysiwygTextView.exists) let sendButton = app.buttons["sendButton"] - XCTAssertTrue(sendButton.exists) - XCTAssertFalse(sendButton.isEnabled) + XCTAssertFalse(sendButton.exists) let cancelButton = app.buttons["cancelButton"] XCTAssertTrue(cancelButton.exists) @@ -51,7 +49,7 @@ final class ComposerUITests: MockScreenTestCase { wysiwygTextView.tap() wysiwygTextView.typeText("test") - XCTAssertTrue(sendButton.isEnabled) + XCTAssertTrue(sendButton.exists) XCTAssertFalse(app.buttons["editButton"].exists) cancelButton.tap() @@ -66,8 +64,7 @@ final class ComposerUITests: MockScreenTestCase { let wysiwygTextView = app.textViews.allElementsBoundByIndex[0] XCTAssertTrue(wysiwygTextView.exists) let editButton = app.buttons["editButton"] - XCTAssertTrue(editButton.exists) - XCTAssertFalse(editButton.isEnabled) + XCTAssertFalse(editButton.exists) let cancelButton = app.buttons["cancelButton"] XCTAssertTrue(cancelButton.exists) @@ -78,7 +75,7 @@ final class ComposerUITests: MockScreenTestCase { wysiwygTextView.tap() wysiwygTextView.typeText("test") - XCTAssertTrue(editButton.isEnabled) + XCTAssertTrue(editButton.exists) XCTAssertFalse(app.buttons["sendButton"].exists) cancelButton.tap() diff --git a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift index 0bcfd6ffd..be7577e12 100644 --- a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift +++ b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift @@ -26,7 +26,7 @@ struct Composer: View { @Environment(\.theme) private var theme: ThemeSwiftUI @State private var focused = false - @State private var isActionButtonEnabled = false + @State private var isActionButtonShowing = false private let horizontalPadding: CGFloat = 12 private let borderHeight: CGFloat = 40 @@ -148,7 +148,7 @@ struct Composer: View { .resizable() .foregroundColor(theme.colors.tertiaryContent) .frame(width: 14, height: 14) - + } .frame(width: 36, height: 36) .background(Circle().fill(theme.colors.system)) @@ -159,16 +159,6 @@ struct Composer: View { } .frame(height: 44) Spacer() - // ZStack { - // TODO: Add support for voice messages - // Button { - // - // } label: { - // Image(Asset.Images.voiceMessageRecordButtonDefault.name) - // .foregroundColor(theme.colors.tertiaryContent) - // } - // .isHidden(showSendButton) - // .isHidden(true) Button { sendMessageAction(wysiwygViewModel.content) wysiwygViewModel.clearContent() @@ -181,18 +171,18 @@ struct Composer: View { } .frame(width: 36, height: 36) .padding(.leading, 8) - .disabled(!isActionButtonEnabled) - .opacity(isActionButtonEnabled ? 1 : 0.3) - .animation(.easeInOut(duration: 0.15), value: isActionButtonEnabled) + .isHidden(!isActionButtonShowing) .accessibilityIdentifier(actionButtonAccessibilityIdentifier) .accessibilityLabel(VectorL10n.send) - .onChange(of: wysiwygViewModel.isContentEmpty) { empty in - isActionButtonEnabled = !empty + .onChange(of: wysiwygViewModel.isContentEmpty) { isEmpty in + viewModel.send(viewAction: .contentDidChange(isEmpty: isEmpty)) + withAnimation(.easeInOut(duration: 0.15)) { + isActionButtonShowing = !isEmpty + } } } .padding(.horizontal, 12) .padding(.bottom, 4) - .animation(.none) } } } diff --git a/RiotSwiftUI/Modules/Room/Composer/ViewModel/ComposerViewModel.swift b/RiotSwiftUI/Modules/Room/Composer/ViewModel/ComposerViewModel.swift index 65fd747b6..1e44ed049 100644 --- a/RiotSwiftUI/Modules/Room/Composer/ViewModel/ComposerViewModel.swift +++ b/RiotSwiftUI/Modules/Room/Composer/ViewModel/ComposerViewModel.swift @@ -60,6 +60,8 @@ final class ComposerViewModel: ComposerViewModelType, ComposerViewModelProtocol switch viewAction { case .cancel: callback?(.cancel) + case let .contentDidChange(isEmpty): + callback?(.contentDidChange(isEmpty: isEmpty)) } } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Test/Unit/UserOtherSessionsViewModelTests.swift b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Test/Unit/UserOtherSessionsViewModelTests.swift index 271812859..782bdac4f 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Test/Unit/UserOtherSessionsViewModelTests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Test/Unit/UserOtherSessionsViewModelTests.swift @@ -58,7 +58,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .inactive, isEditModeEnabled: false) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: "Title", - items: expectedItems, + sessionItems: expectedItems, header: inactiveSectionHeader, emptyItemsTitle: VectorL10n.userOtherSessionNoInactiveSessions, allItemsSelected: false) @@ -74,7 +74,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .all, isEditModeEnabled: false) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: "Title", - items: expectedItems, + sessionItems: expectedItems, header: allSectionHeader, emptyItemsTitle: "", allItemsSelected: false) @@ -90,7 +90,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .unverified, isEditModeEnabled: false) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: "Title", - items: expectedItems, + sessionItems: expectedItems, header: unverifiedSectionHeader, emptyItemsTitle: VectorL10n.userOtherSessionNoUnverifiedSessions, allItemsSelected: false) @@ -106,7 +106,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .verified, isEditModeEnabled: false) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: "Title", - items: expectedItems, + sessionItems: expectedItems, header: verifiedSectionHeader, emptyItemsTitle: VectorL10n.userOtherSessionNoVerifiedSessions, allItemsSelected: false) @@ -120,7 +120,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .verified, isEditModeEnabled: false) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: "Title", - items: [], + sessionItems: [], header: verifiedSectionHeader, emptyItemsTitle: VectorL10n.userOtherSessionNoVerifiedSessions, allItemsSelected: false) @@ -134,7 +134,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .unverified, isEditModeEnabled: false) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: "Title", - items: [], + sessionItems: [], header: unverifiedSectionHeader, emptyItemsTitle: VectorL10n.userOtherSessionNoUnverifiedSessions, allItemsSelected: false) @@ -148,7 +148,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .inactive, isEditModeEnabled: false) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: "Title", - items: [], + sessionItems: [], header: inactiveSectionHeader, emptyItemsTitle: VectorL10n.userOtherSessionNoInactiveSessions, allItemsSelected: false) @@ -167,7 +167,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .all, isEditModeEnabled: true) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: VectorL10n.userOtherSessionSelectedCount("2"), - items: expectedItems, + sessionItems: expectedItems, header: allSectionHeader, emptyItemsTitle: "", allItemsSelected: true) @@ -186,7 +186,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .all, isEditModeEnabled: true) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: VectorL10n.userOtherSessionSelectedCount("0"), - items: expectedItems, + sessionItems: expectedItems, header: allSectionHeader, emptyItemsTitle: "", allItemsSelected: false) @@ -204,7 +204,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .all, isEditModeEnabled: true) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: VectorL10n.userOtherSessionSelectedCount("1"), - items: expectedItems, + sessionItems: expectedItems, header: allSectionHeader, emptyItemsTitle: "", allItemsSelected: false) @@ -222,7 +222,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .all, isEditModeEnabled: true) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: VectorL10n.userOtherSessionSelectedCount("2"), - items: expectedItems, + sessionItems: expectedItems, header: allSectionHeader, emptyItemsTitle: "", allItemsSelected: true) @@ -240,7 +240,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .all, isEditModeEnabled: true) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: VectorL10n.userOtherSessionSelectedCount("0"), - items: expectedItems, + sessionItems: expectedItems, header: allSectionHeader, emptyItemsTitle: "", allItemsSelected: false) @@ -261,7 +261,7 @@ class UserOtherSessionsViewModelTests: XCTestCase { let bindings = UserOtherSessionsBindings(filter: .all, isEditModeEnabled: true) let expectedState = UserOtherSessionsViewState(bindings: bindings, title: VectorL10n.userOtherSessionSelectedCount("0"), - items: expectedItems, + sessionItems: expectedItems, header: allSectionHeader, emptyItemsTitle: "", allItemsSelected: false) diff --git a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/UserOtherSessionsModels.swift b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/UserOtherSessionsModels.swift index 83eb410ff..c2ee312e8 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/UserOtherSessionsModels.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/UserOtherSessionsModels.swift @@ -35,7 +35,7 @@ enum UserOtherSessionsViewModelResult: Equatable { struct UserOtherSessionsViewState: BindableState, Equatable { var bindings: UserOtherSessionsBindings var title: String - var items: [UserSessionListItemViewData] + var sessionItems: [UserSessionListItemViewData] var header: UserOtherSessionsHeaderViewData var emptyItemsTitle: String var allItemsSelected: Bool diff --git a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/UserOtherSessionsViewModel.swift b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/UserOtherSessionsViewModel.swift index 8a65650f1..015b723c2 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/UserOtherSessionsViewModel.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/UserOtherSessionsViewModel.swift @@ -30,10 +30,10 @@ class UserOtherSessionsViewModel: UserOtherSessionsViewModelType, UserOtherSessi self.sessionInfos = sessionInfos defaultTitle = title let bindings = UserOtherSessionsBindings(filter: filter, isEditModeEnabled: false) - let items = filter.filterSessionInfos(sessionInfos: sessionInfos, selectedSessions: selectedSessions) + let sessionItems = filter.filterSessionInfos(sessionInfos: sessionInfos, selectedSessions: selectedSessions) super.init(initialViewState: UserOtherSessionsViewState(bindings: bindings, title: title, - items: items, + sessionItems: sessionItems, header: filter.userOtherSessionsViewHeader, emptyItemsTitle: filter.userOtherSessionsViewEmptyResultsTitle, allItemsSelected: false)) @@ -87,7 +87,7 @@ class UserOtherSessionsViewModel: UserOtherSessionsViewModelType, UserOtherSessi private func updateViewState() { let currentFilter = state.bindings.filter - state.items = currentFilter.filterSessionInfos(sessionInfos: sessionInfos, selectedSessions: selectedSessions) + state.sessionItems = currentFilter.filterSessionInfos(sessionInfos: sessionInfos, selectedSessions: selectedSessions) state.header = currentFilter.userOtherSessionsViewHeader if state.bindings.isEditModeEnabled { diff --git a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessions.swift b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessions.swift index 8df984150..ddab470f1 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessions.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessions.swift @@ -24,7 +24,7 @@ struct UserOtherSessions: View { var body: some View { ScrollView { SwiftUI.Section { - if viewModel.viewState.items.isEmpty { + if viewModel.viewState.sessionItems.isEmpty { noItemsView() } else { itemsView() @@ -81,7 +81,7 @@ struct UserOtherSessions: View { private func itemsView() -> some View { LazyVStack(spacing: 0) { - ForEach(viewModel.viewState.items) { viewData in + ForEach(viewModel.viewState.sessionItems) { viewData in UserSessionListItem(viewData: viewData, isEditModeEnabled: viewModel.isEditModeEnabled, onBackgroundTap: { sessionId in viewModel.send(viewAction: .userOtherSessionSelected(sessionId: sessionId)) }, diff --git a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsToolbar.swift b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsToolbar.swift index cef6f9c76..5a03a8d2a 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsToolbar.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsToolbar.swift @@ -48,7 +48,7 @@ struct UserOtherSessionsToolbar: ToolbarContent { } else { filterMenuButton() .offset(x: 12) - kebabMenu() + optionsMenu() } } } @@ -77,7 +77,7 @@ struct UserOtherSessionsToolbar: ToolbarContent { } } - private func kebabMenu() -> some View { + private func optionsMenu() -> some View { Button { } label: { Menu { Button { diff --git a/changelog.d/6941.feature b/changelog.d/6941.feature new file mode 100644 index 000000000..f9c3d32ea --- /dev/null +++ b/changelog.d/6941.feature @@ -0,0 +1 @@ +Added voice message support to the Rich Text Composer \ No newline at end of file