From ae603b2883ab9e5807abb2d484deb5ab8653b995 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Tue, 29 Nov 2022 18:52:19 +0100 Subject: [PATCH 01/13] centring the toggle button when the corner radius is half --- RiotSwiftUI/Modules/Room/Composer/View/Composer.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift index 87c7cbe7a7..af02a6f11c 100644 --- a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift +++ b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift @@ -43,13 +43,17 @@ struct Composer: View { } private var cornerRadius: CGFloat { - if viewModel.viewState.shouldDisplayContext || wysiwygViewModel.idealHeight > wysiwygViewModel.minHeight { + if shouldFixRoundCorner { return 14 } else { return borderHeight / 2 } } + private var shouldFixRoundCorner: Bool { + viewModel.viewState.shouldDisplayContext || wysiwygViewModel.idealHeight > wysiwygViewModel.minHeight + } + private var actionButtonAccessibilityIdentifier: String { viewModel.viewState.sendMode == .edit ? "editButton" : "sendButton" } @@ -103,7 +107,7 @@ struct Composer: View { .padding(.top, 8) .padding(.horizontal, horizontalPadding) } - HStack(alignment: .top, spacing: 0) { + HStack(alignment: shouldFixRoundCorner ? .top : .center, spacing: 0) { WysiwygComposerView( focused: $viewModel.focused, viewModel: wysiwygViewModel From 84c9c7fa5025af09d43dd652a6dd52c9bf8b13de Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Tue, 29 Nov 2022 19:13:49 +0100 Subject: [PATCH 02/13] spacing improvement from bottom in plain text mode --- .../WYSIWYGInputToolbar/WysiwygInputToolbarView.swift | 8 ++++---- RiotSwiftUI/Modules/Room/Composer/View/Composer.swift | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift index cee4a9c119..c343814039 100644 --- a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift +++ b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift @@ -217,9 +217,9 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp keyboardHeight = keyboardRectangle.height UIView.performWithoutAnimation { if self.isMaximised { - self.voiceMessageBottomConstraint?.constant = keyboardHeight - (window?.safeAreaInsets.bottom ?? 0) + 4 + self.voiceMessageBottomConstraint?.constant = keyboardHeight - (window?.safeAreaInsets.bottom ?? 0) + 2 } else { - self.voiceMessageBottomConstraint?.constant = 4 + self.voiceMessageBottomConstraint?.constant = 2 } self.layoutIfNeeded() } @@ -229,7 +229,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp @objc private func keyboardWillHide(_ notification: Notification) { if self.isMaximised { UIView.performWithoutAnimation { - self.voiceMessageBottomConstraint?.constant = 4 + self.voiceMessageBottomConstraint?.constant = 2 self.layoutIfNeeded() } } @@ -361,7 +361,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp voiceMessageToolbarView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.deactivate(voiceMessageToolbarView.containersTopConstraints) addSubview(voiceMessageToolbarView) - let bottomConstraint = hostingViewController.view.bottomAnchor.constraint(equalTo: voiceMessageToolbarView.bottomAnchor, constant: 4) + let bottomConstraint = hostingViewController.view.bottomAnchor.constraint(equalTo: voiceMessageToolbarView.bottomAnchor, constant: 2) voiceMessageBottomConstraint = bottomConstraint NSLayoutConstraint.activate( [ diff --git a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift index af02a6f11c..5d8ec53203 100644 --- a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift +++ b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift @@ -214,10 +214,12 @@ struct Composer: View { HStack(alignment: .bottom, spacing: 0) { if !viewModel.viewState.textFormattingEnabled { sendMediaButton + .padding(.bottom, 1) } composerContainer if !viewModel.viewState.textFormattingEnabled { sendButton + .padding(.bottom, 1) } } if viewModel.viewState.textFormattingEnabled { From e7b9b2e8d7b7319e5dcda6b9d2c586320cf2085d Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 11:11:00 +0100 Subject: [PATCH 03/13] scrolling disabled, better intrinsic size, changed asset --- .../Contents.json | 6 +- .../Frame 143.png | Bin 0 -> 447 bytes .../Frame 143@2x.png | Bin 0 -> 738 bytes .../Frame 143@3x.png | Bin 0 -> 924 bytes .../action_formatting_disabled.png | Bin 513 -> 0 bytes .../action_formatting_disabled@2x.png | Bin 894 -> 0 bytes .../action_formatting_disabled@3x.png | Bin 1141 -> 0 bytes .../ComposerCreateActionListCoordinator.swift | 12 +- ...kComposerCreateActionListScreenState.swift | 1 + .../ComposerCreateActionListModels.swift | 1 + .../View/ComposerCreateActionList.swift | 104 ++++++++++-------- 11 files changed, 74 insertions(+), 50 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Frame 143.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Frame 143@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Frame 143@3x.png delete mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/action_formatting_disabled.png delete mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/action_formatting_disabled@2x.png delete mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/action_formatting_disabled@3x.png diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Contents.json index dbee5479fb..3451f0d6cc 100644 --- a/Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Contents.json @@ -1,17 +1,17 @@ { "images" : [ { - "filename" : "action_formatting_disabled.png", + "filename" : "Frame 143.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "action_formatting_disabled@2x.png", + "filename" : "Frame 143@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "action_formatting_disabled@3x.png", + "filename" : "Frame 143@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Frame 143.png b/Riot/Assets/Images.xcassets/Room/Actions/action_formatting_disabled.imageset/Frame 143.png new file mode 100644 index 0000000000000000000000000000000000000000..8cc5f79e868fb329552601364f793e2804e651fd GIT binary patch literal 447 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 diff --git a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Coordinator/ComposerCreateActionListCoordinator.swift b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Coordinator/ComposerCreateActionListCoordinator.swift index f5adcc75ac..eebab63f0f 100644 --- a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Coordinator/ComposerCreateActionListCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Coordinator/ComposerCreateActionListCoordinator.swift @@ -41,14 +41,23 @@ final class ComposerCreateActionListCoordinator: NSObject, Coordinator, Presenta // MARK: - Setup init(actions: [ComposerCreateAction], wysiwygEnabled: Bool, textFormattingEnabled: Bool) { + let isScrollingEnabled: Bool + if #available(iOS 16, *) { + isScrollingEnabled = false + } else { + isScrollingEnabled = true + } viewModel = ComposerCreateActionListViewModel(initialViewState: ComposerCreateActionListViewState( actions: actions, wysiwygEnabled: wysiwygEnabled, + isScrollingEnabled: isScrollingEnabled, bindings: ComposerCreateActionListBindings(textFormattingEnabled: textFormattingEnabled))) view = ComposerCreateActionList(viewModel: viewModel.context) let hostingVC = VectorHostingController(rootView: view) + let height = hostingVC.sizeThatFits(in: CGSize(width: hostingVC.view.frame.width, height: UIView.layoutFittingCompressedSize.height)).height hostingVC.bottomSheetPreferences = VectorHostingBottomSheetPreferences( - detents: [.custom(height: 470)], + // on iOS 15 custom will be replaced by medium which may require some scrolling + detents: [.custom(height: height)], prefersGrabberVisible: true, cornerRadius: 20, prefersScrollingExpandsWhenScrolledToEdge: false @@ -56,6 +65,7 @@ final class ComposerCreateActionListCoordinator: NSObject, Coordinator, Presenta hostingController = hostingVC super.init() hostingVC.presentationController?.delegate = self + hostingVC.bottomSheetPreferences?.setup(viewController: hostingVC) } // MARK: - Public diff --git a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/MockComposerCreateActionListScreenState.swift b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/MockComposerCreateActionListScreenState.swift index cb1a53b886..8089ab7ae2 100644 --- a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/MockComposerCreateActionListScreenState.swift +++ b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/MockComposerCreateActionListScreenState.swift @@ -36,6 +36,7 @@ enum MockComposerCreateActionListScreenState: MockScreenState, CaseIterable { let viewModel = ComposerCreateActionListViewModel(initialViewState: ComposerCreateActionListViewState( actions: actions, wysiwygEnabled: true, + isScrollingEnabled: false, bindings: ComposerCreateActionListBindings(textFormattingEnabled: true))) return ( diff --git a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Model/ComposerCreateActionListModels.swift b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Model/ComposerCreateActionListModels.swift index 6c42041b7c..d1194e1755 100644 --- a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Model/ComposerCreateActionListModels.swift +++ b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Model/ComposerCreateActionListModels.swift @@ -38,6 +38,7 @@ struct ComposerCreateActionListViewState: BindableState { /// The list of composer create actions to display to the user let actions: [ComposerCreateAction] let wysiwygEnabled: Bool + let isScrollingEnabled: Bool var bindings: ComposerCreateActionListBindings } diff --git a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift index 5da2b1d119..80a7f7f674 100644 --- a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift +++ b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift @@ -32,56 +32,68 @@ struct ComposerCreateActionList: View { // MARK: Public @ObservedObject var viewModel: ComposerCreateActionListViewModel.Context - - var body: some View { - ScrollView { - VStack(alignment: .leading) { - ForEach(viewModel.viewState.actions) { action in - HStack(spacing: 16) { - Image(action.icon) - .renderingMode(.template) - .foregroundColor(theme.colors.accent) - Text(action.title) - .foregroundColor(theme.colors.primaryContent) - .font(theme.fonts.body) - .accessibilityIdentifier(action.accessibilityIdentifier) - Spacer() - } - .contentShape(Rectangle()) - .onTapGesture { - viewModel.send(viewAction: .selectAction(action)) - } - .padding(.horizontal, 16) - .padding(.vertical, 12) + + private var internalView: some View { + VStack(alignment: .leading) { + ForEach(viewModel.viewState.actions) { action in + HStack(spacing: 16) { + Image(action.icon) + .renderingMode(.template) + .foregroundColor(theme.colors.accent) + Text(action.title) + .foregroundColor(theme.colors.primaryContent) + .font(theme.fonts.body) + .accessibilityIdentifier(action.accessibilityIdentifier) + Spacer() } - if viewModel.viewState.wysiwygEnabled { - SeparatorLine() - HStack(spacing: 16) { - Image(textFormattingIcon) - .renderingMode(.template) - .foregroundColor(theme.colors.accent) - Text(VectorL10n.wysiwygComposerStartActionTextFormatting) - .foregroundColor(theme.colors.primaryContent) - .font(theme.fonts.body) - .accessibilityIdentifier("textFormatting") - Spacer() - Toggle("", isOn: $viewModel.textFormattingEnabled) - .toggleStyle(ComposerToggleActionStyle()) - .labelsHidden() - .onChange(of: viewModel.textFormattingEnabled) { isOn in - viewModel.send(viewAction: .toggleTextFormatting(isOn)) - } - } - .contentShape(Rectangle()) - .padding(.horizontal, 16) - .padding(.vertical, 12) - + .contentShape(Rectangle()) + .onTapGesture { + viewModel.send(viewAction: .selectAction(action)) } + .padding(.horizontal, 16) + .padding(.vertical, 12) + } + if viewModel.viewState.wysiwygEnabled { + SeparatorLine() + HStack(spacing: 16) { + Image(textFormattingIcon) + .renderingMode(.template) + .foregroundColor(theme.colors.accent) + Text(VectorL10n.wysiwygComposerStartActionTextFormatting) + .foregroundColor(theme.colors.primaryContent) + .font(theme.fonts.body) + .accessibilityIdentifier("textFormatting") + Spacer() + Toggle("", isOn: $viewModel.textFormattingEnabled) + .toggleStyle(ComposerToggleActionStyle()) + .labelsHidden() + .onChange(of: viewModel.textFormattingEnabled) { isOn in + viewModel.send(viewAction: .toggleTextFormatting(isOn)) + } + } + .contentShape(Rectangle()) + .padding(.horizontal, 16) + .padding(.vertical, 12) + + } + } + } + + var body: some View { + if viewModel.viewState.isScrollingEnabled { + ScrollView { + internalView + } + .padding(.top, 23) + .background(theme.colors.background.ignoresSafeArea()) + } else { + VStack { + internalView + Spacer() } - Spacer() + .padding(.top, 23) + .background(theme.colors.background.ignoresSafeArea()) } - .padding(.top, 23) - .background(theme.colors.background.ignoresSafeArea()) } } From a5dc378cd727bc6ab7ba0428be74636d70634013 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 11:37:12 +0100 Subject: [PATCH 04/13] all the row is tappable and fixed an issue with the tests --- .../Test/Unit/ComposerCreateActionListTests.swift | 1 + .../CreateActionList/View/ComposerCreateActionList.swift | 3 +++ 2 files changed, 4 insertions(+) diff --git a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Test/Unit/ComposerCreateActionListTests.swift b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Test/Unit/ComposerCreateActionListTests.swift index 35532a2124..c1e158d9bb 100644 --- a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Test/Unit/ComposerCreateActionListTests.swift +++ b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/Test/Unit/ComposerCreateActionListTests.swift @@ -27,6 +27,7 @@ class ComposerCreateActionListTests: XCTestCase { initialViewState: ComposerCreateActionListViewState( actions: ComposerCreateAction.allCases, wysiwygEnabled: true, + isScrollingEnabled: false, bindings: ComposerCreateActionListBindings(textFormattingEnabled: true) ) ) diff --git a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift index 80a7f7f674..6f85ffa876 100644 --- a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift +++ b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift @@ -72,6 +72,9 @@ struct ComposerCreateActionList: View { } } .contentShape(Rectangle()) + .onTapGesture { + viewModel.textFormattingEnabled.toggle() + } .padding(.horizontal, 16) .padding(.vertical, 12) From 8b608b939de037218afb1dc27faa5ec7e200405f Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 11:46:40 +0100 Subject: [PATCH 05/13] design improvements --- changelog.d/pr-7127.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/pr-7127.change diff --git a/changelog.d/pr-7127.change b/changelog.d/pr-7127.change new file mode 100644 index 0000000000..0ab8abeced --- /dev/null +++ b/changelog.d/pr-7127.change @@ -0,0 +1 @@ +Rich Text Editor: Design Improvements. \ No newline at end of file From 1b6cabf2a7961427ed5898262bed1599ce74f73e Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 13:27:07 +0100 Subject: [PATCH 06/13] fix for iOS 15 fullscreen mode not working --- Riot/Modules/Room/RoomViewController.swift | 10 +++++++++- .../WYSIWYGInputToolbar/WysiwygInputToolbarView.swift | 3 +++ RiotSwiftUI/Modules/Room/Composer/View/Composer.swift | 4 +--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Room/RoomViewController.swift b/Riot/Modules/Room/RoomViewController.swift index c3857db81d..9204eeae9c 100644 --- a/Riot/Modules/Room/RoomViewController.swift +++ b/Riot/Modules/Room/RoomViewController.swift @@ -177,7 +177,15 @@ extension RoomViewController { optionalTextView?.becomeFirstResponder() originalRect = wysiwygInputToolbar.convert(wysiwygInputToolbar.frame, to: view) } - wysiwygInputToolbar.showKeyboard() + // This tirggers a SwiftUI update that is handled correctly on iOS 16, but needs to be dispatchted async on older versions + // Dispatching on iOS 16 instead causes some weird SwiftUI update behaviours + if #available(iOS 16, *) { + wysiwygInputToolbar.showKeyboard() + } else { + DispatchQueue.main.async { + wysiwygInputToolbar.showKeyboard() + } + } roomInputToolbarContainer.removeFromSuperview() let dimmingView = UIView() dimmingView.translatesAutoresizingMaskIntoConstraints = false diff --git a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift index c343814039..21cc7023cf 100644 --- a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift +++ b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift @@ -165,6 +165,9 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp guard let self = self else { return } self.toolbarViewDelegate?.didChangeMaximisedState(value) self.hostingViewController.view.layer.cornerRadius = value ? 20 : 0 + if !value { + self.voiceMessageBottomConstraint?.constant = 2 + } } ] diff --git a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift index 5d8ec53203..25bd5c868c 100644 --- a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift +++ b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift @@ -143,9 +143,7 @@ struct Composer: View { .animation(.easeInOut(duration: resizeAnimationDuration), value: wysiwygViewModel.idealHeight) .padding(.top, 8) .onTapGesture { - if viewModel.focused { - viewModel.focused = true - } + viewModel.focused = true } } From 7869b8f0a24005e6efa5e183b523aa1fc7c3cbfb Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 13:41:08 +0100 Subject: [PATCH 07/13] fix for iPhone 14 --- .../WYSIWYGInputToolbar/WysiwygInputToolbarView.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift index 21cc7023cf..27d3692025 100644 --- a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift +++ b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift @@ -296,7 +296,12 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp private func updateTextViewHeight() { let height = UIScreen.main.bounds.height - let barOffset: CGFloat = 68 + let barOffset: CGFloat + if let topSafeArea = window?.safeAreaInsets.top, topSafeArea >= 68 { + barOffset = topSafeArea + } else { + barOffset = 68 + } let toolbarHeight: CGFloat = 96 let finalHeight = height - keyboardHeight - toolbarHeight - barOffset wysiwygViewModel.maxExpandedHeight = finalHeight From 447721f87d05bc88af64c9a3237f96c157314c24 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 14:04:38 +0100 Subject: [PATCH 08/13] better fix for iPhone 14 --- .../WYSIWYGInputToolbar/WysiwygInputToolbarView.swift | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift index 27d3692025..b5e2a33a9c 100644 --- a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift +++ b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift @@ -296,13 +296,8 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp private func updateTextViewHeight() { let height = UIScreen.main.bounds.height - let barOffset: CGFloat - if let topSafeArea = window?.safeAreaInsets.top, topSafeArea >= 68 { - barOffset = topSafeArea - } else { - barOffset = 68 - } - let toolbarHeight: CGFloat = 96 + let barOffset: CGFloat = 68 + let toolbarHeight: CGFloat = sendMode == .send ? 96 : 110 let finalHeight = height - keyboardHeight - toolbarHeight - barOffset wysiwygViewModel.maxExpandedHeight = finalHeight if finalHeight < 200 { @@ -347,6 +342,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp set { viewModel.sendMode = ComposerSendMode(from: newValue) updatePlaceholderText() + updateTextViewHeight() } } From 0f1c810b580a205b5ac888407afa8321059ae90a Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 14:34:21 +0100 Subject: [PATCH 09/13] toggle now uses iOS style --- .../View/ComposerCreateActionList.swift | 34 +------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift index 6f85ffa876..706c2f1d92 100644 --- a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift +++ b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift @@ -65,8 +65,8 @@ struct ComposerCreateActionList: View { .accessibilityIdentifier("textFormatting") Spacer() Toggle("", isOn: $viewModel.textFormattingEnabled) - .toggleStyle(ComposerToggleActionStyle()) .labelsHidden() + .toggleStyle(SwitchToggleStyle(tint: theme.colors.accent)) .onChange(of: viewModel.textFormattingEnabled) { isOn in viewModel.send(viewAction: .toggleTextFormatting(isOn)) } @@ -108,35 +108,3 @@ struct ComposerCreateActionList_Previews: PreviewProvider { stateRenderer.screenGroup() } } - -struct ComposerToggleActionStyle: ToggleStyle { - @Environment(\.theme) private var theme - - func makeBody(configuration: Configuration) -> some View { - HStack { - Rectangle() - .foregroundColor(.clear) - .frame(width: 50, height: 30, alignment: .center) - .overlay( - Rectangle() - .foregroundColor(configuration.isOn - ? theme.colors.accent.opacity(0.5) - : theme.colors.primaryContent.opacity(0.25)) - .cornerRadius(7) - .padding(.all, 8) - ) - .overlay( - Circle() - .foregroundColor(configuration.isOn - ? theme.colors.accent - : theme.colors.background) - .padding(.all, 3) - .offset(x: configuration.isOn ? 11 : -11, y: 0) - .shadow(radius: configuration.isOn ? 0.0 : 2.0) - .animation(Animation.linear(duration: 0.1)) - - ).cornerRadius(20) - .onTapGesture { configuration.isOn.toggle() } - } - } -} From 9f789e25d9221ebceed803c467945e28b46ccdea Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 15:05:36 +0100 Subject: [PATCH 10/13] fix changelog --- changelog.d/7118.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7118.bugfix diff --git a/changelog.d/7118.bugfix b/changelog.d/7118.bugfix new file mode 100644 index 0000000000..af402294f7 --- /dev/null +++ b/changelog.d/7118.bugfix @@ -0,0 +1 @@ +Rich Text Editor: Fixed a bug that prevented fullscreen mode to work on iOS 15. \ No newline at end of file From 24b387c37dc9ff2c8d3193d37c31c1f5beaebec0 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 15:09:05 +0100 Subject: [PATCH 11/13] reversed unused hunk --- RiotSwiftUI/Modules/Room/Composer/View/Composer.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift index 25bd5c868c..5d8ec53203 100644 --- a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift +++ b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift @@ -143,7 +143,9 @@ struct Composer: View { .animation(.easeInOut(duration: resizeAnimationDuration), value: wysiwygViewModel.idealHeight) .padding(.top, 8) .onTapGesture { - viewModel.focused = true + if viewModel.focused { + viewModel.focused = true + } } } From 314f10c2c1b18706df4676f1c2fd69d0fd0c9696 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 15:37:00 +0100 Subject: [PATCH 12/13] fix for 7130 ? --- .../WysiwygInputToolbarView.swift | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift index b5e2a33a9c..5b9c7d4a71 100644 --- a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift +++ b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift @@ -218,23 +218,17 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue { let keyboardRectangle = keyboardFrame.cgRectValue keyboardHeight = keyboardRectangle.height - UIView.performWithoutAnimation { - if self.isMaximised { - self.voiceMessageBottomConstraint?.constant = keyboardHeight - (window?.safeAreaInsets.bottom ?? 0) + 2 - } else { - self.voiceMessageBottomConstraint?.constant = 2 - } - self.layoutIfNeeded() + if self.isMaximised { + self.voiceMessageBottomConstraint?.constant = keyboardHeight - (window?.safeAreaInsets.bottom ?? 0) + 2 + } else { + self.voiceMessageBottomConstraint?.constant = 2 } } } @objc private func keyboardWillHide(_ notification: Notification) { if self.isMaximised { - UIView.performWithoutAnimation { - self.voiceMessageBottomConstraint?.constant = 2 - self.layoutIfNeeded() - } + self.voiceMessageBottomConstraint?.constant = 2 } } @@ -280,7 +274,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp } ) } - + private func registerThemeServiceDidChangeThemeNotification() { NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) } @@ -345,7 +339,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp updateTextViewHeight() } } - + /// Whether text formatting is currently enabled in the composer. var textFormattingEnabled: Bool { get { From 1c28ba3914dbddb8b67c7710157b5137cd30228a Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Wed, 30 Nov 2022 15:42:54 +0100 Subject: [PATCH 13/13] changelog --- changelog.d/7130.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7130.bugfix diff --git a/changelog.d/7130.bugfix b/changelog.d/7130.bugfix new file mode 100644 index 0000000000..a52b68f4f4 --- /dev/null +++ b/changelog.d/7130.bugfix @@ -0,0 +1 @@ +Rich Text Composer: Fix for fullscreen mode breaking sometimes when opening it when keyboard is not showing. \ No newline at end of file