diff --git a/Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved index 1e81323700..132150a17a 100644 --- a/Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift", "state" : { - "revision" : "3f72aeab7d7e04b52ff3f735ab79a75993f97ef2", - "version" : "0.22.0" + "revision" : "f25189fb9b37eb77fad016ee8f0b0346c5310644", + "version" : "1.1.0" } }, { diff --git a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift index d611fb06ad..db6cc81939 100644 --- a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift +++ b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift @@ -44,15 +44,26 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp private var voiceMessageBottomConstraint: NSLayoutConstraint? private var hostingViewController: VectorHostingController! private var wysiwygViewModel = WysiwygComposerViewModel( - parserStyle: HTMLParserStyle(textColor: ThemeService.shared().theme.colors.primaryContent, - linkColor: ThemeService.shared().theme.colors.links, - codeBackgroundColor: ThemeService.shared().theme.selectedBackgroundColor, - codeBorderColor: ThemeService.shared().theme.textQuinaryColor, - quoteBackgroundColor: ThemeService.shared().theme.selectedBackgroundColor, - quoteBorderColor: ThemeService.shared().theme.textQuinaryColor, - borderWidth: 1.0, - cornerRadius: 4.0) + parserStyle: WysiwygInputToolbarView.parserStyle ) + /// Compute current HTML parser style for composer. + private static var parserStyle: HTMLParserStyle { + return HTMLParserStyle( + textColor: ThemeService.shared().theme.colors.primaryContent, + linkColor: ThemeService.shared().theme.colors.links, + codeBlockStyle: BlockStyle(backgroundColor: ThemeService.shared().theme.selectedBackgroundColor, + borderColor: ThemeService.shared().theme.textQuinaryColor, + borderWidth: 1.0, + cornerRadius: 4.0, + padding: .init(horizontal: 10.0, vertical: 12.0), + type: .background), + quoteBlockStyle: BlockStyle(backgroundColor: ThemeService.shared().theme.selectedBackgroundColor, + borderColor: ThemeService.shared().theme.selectedBackgroundColor, + borderWidth: 0.0, + cornerRadius: 0.0, + padding: .init(horizontal: 25.0, vertical: 12.0), + type: .side(offset: 5, width: 4))) + } private var viewModel: ComposerViewModelProtocol! private var isLandscapePhone: Bool { @@ -304,14 +315,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp private func update(theme: Theme) { hostingViewController.view.backgroundColor = theme.colors.background - wysiwygViewModel.parserStyle = HTMLParserStyle(textColor: ThemeService.shared().theme.colors.primaryContent, - linkColor: ThemeService.shared().theme.colors.links, - codeBackgroundColor: ThemeService.shared().theme.selectedBackgroundColor, - codeBorderColor: ThemeService.shared().theme.textQuinaryColor, - quoteBackgroundColor: ThemeService.shared().theme.selectedBackgroundColor, - quoteBorderColor: ThemeService.shared().theme.textQuinaryColor, - borderWidth: 1.0, - cornerRadius: 4.0) + wysiwygViewModel.parserStyle = WysiwygInputToolbarView.parserStyle } private func updateTextViewHeight() { diff --git a/RiotSwiftUI/Modules/Room/Composer/Model/ComposerModels.swift b/RiotSwiftUI/Modules/Room/Composer/Model/ComposerModels.swift index 800494c5db..98d7febf6d 100644 --- a/RiotSwiftUI/Modules/Room/Composer/Model/ComposerModels.swift +++ b/RiotSwiftUI/Modules/Room/Composer/Model/ComposerModels.swift @@ -37,7 +37,7 @@ enum FormatType { case unorderedList case orderedList case indent - case unIndent + case unindent case inlineCode case codeBlock case quote @@ -48,6 +48,18 @@ extension FormatType: CaseIterable, Identifiable { var id: Self { self } } +extension FormatType { + /// Return true if the format type is an indentation action. + var isIndentType: Bool { + switch self { + case .indent, .unindent: + return true + default: + return false + } + } +} + extension FormatItem: Identifiable { var id: FormatType { type } } @@ -70,7 +82,7 @@ extension FormatItem { return Asset.Images.numberedList.name case .indent: return Asset.Images.indentIncrease.name - case .unIndent: + case .unindent: return Asset.Images.indentDecrease.name case .inlineCode: return Asset.Images.code.name @@ -99,7 +111,7 @@ extension FormatItem { return "orderedListButton" case .indent: return "indentListButton" - case .unIndent: + case .unindent: return "unIndentButton" case .inlineCode: return "inlineCodeButton" @@ -128,7 +140,7 @@ extension FormatItem { return VectorL10n.wysiwygComposerFormatActionOrderedList case .indent: return VectorL10n.wysiwygComposerFormatActionIndent - case .unIndent: + case .unindent: return VectorL10n.wysiwygComposerFormatActionUnIndent case .inlineCode: return VectorL10n.wysiwygComposerFormatActionInlineCode @@ -160,8 +172,8 @@ extension FormatType { return .orderedList case .indent: return .indent - case .unIndent: - return .unIndent + case .unindent: + return .unindent case .inlineCode: return .inlineCode case .codeBlock: @@ -191,8 +203,8 @@ extension FormatType { return .orderedList case .indent: return .indent - case .unIndent: - return .unIndent + case .unindent: + return .unindent case .inlineCode: return .inlineCode case .codeBlock: diff --git a/RiotSwiftUI/Modules/Room/Composer/Test/UI/ComposerUITests.swift b/RiotSwiftUI/Modules/Room/Composer/Test/UI/ComposerUITests.swift index aae6e1682d..72a2fb2adf 100644 --- a/RiotSwiftUI/Modules/Room/Composer/Test/UI/ComposerUITests.swift +++ b/RiotSwiftUI/Modules/Room/Composer/Test/UI/ComposerUITests.swift @@ -158,4 +158,32 @@ final class ComposerUITests: MockScreenTestCase { XCTAssertFalse(minimiseButton.exists) XCTAssertTrue(maximiseButton.exists) } + + func testCreatingListDisplaysIndentButtons() throws { + app.goToScreenWithIdentifier(MockComposerScreenState.send.title) + + XCTAssertFalse(composerToolbarButton(in: app, for: .indent).exists) + XCTAssertFalse(composerToolbarButton(in: app, for: .indent).exists) + // Create a list. + composerToolbarButton(in: app, for: .orderedList).tap() + XCTAssertTrue(composerToolbarButton(in: app, for: .indent).exists) + XCTAssertTrue(composerToolbarButton(in: app, for: .indent).exists) + // Remove the list + composerToolbarButton(in: app, for: .orderedList).tap() + XCTAssertFalse(composerToolbarButton(in: app, for: .indent).exists) + XCTAssertFalse(composerToolbarButton(in: app, for: .indent).exists) + } +} + +private extension ComposerUITests { + /// Returns the button of the composer toolbar associated with given format type. + /// + /// - Parameters: + /// - app: the running app + /// - formatType: format type to look for + /// - Returns: XCUIElement for the button + func composerToolbarButton(in app: XCUIApplication, for formatType: FormatType) -> XCUIElement { + // Note: state is irrelevant here, we're just building this to retrieve the accessibility identifier. + app.buttons[FormatItem(type: formatType, state: .enabled).accessibilityIdentifier] + } } diff --git a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift index 6163f384a2..1413912c2a 100644 --- a/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift +++ b/RiotSwiftUI/Modules/Room/Composer/View/Composer.swift @@ -71,12 +71,15 @@ struct Composer: View { } private var formatItems: [FormatItem] { - FormatType.allCases.map { type in - FormatItem( - type: type, - state: wysiwygViewModel.actionStates[type.composerAction] ?? .disabled - ) - } + return FormatType.allCases + // Exclude indent type outside of lists. + .filter { wysiwygViewModel.isInList || !$0.isIndentType } + .map { type in + FormatItem( + type: type, + state: wysiwygViewModel.actionStates[type.composerAction] ?? .disabled + ) + } } private var composerContainer: some View { @@ -257,6 +260,13 @@ struct Composer: View { } } +private extension WysiwygComposerViewModel { + /// Return true if the selection of the composer is currently located in a list. + var isInList: Bool { + actionStates[.orderedList] == .reversed || actionStates[.unorderedList] == .reversed + } +} + // MARK: Previews struct Composer_Previews: PreviewProvider { diff --git a/changelog.d/pr-7365.change b/changelog.d/pr-7365.change new file mode 100644 index 0000000000..17c2965b68 --- /dev/null +++ b/changelog.d/pr-7365.change @@ -0,0 +1 @@ +Labs: Rich Text Editor: Update to version 1.1.0 diff --git a/project.yml b/project.yml index de099a5077..91ec35475b 100644 --- a/project.yml +++ b/project.yml @@ -53,7 +53,7 @@ packages: branch: main WysiwygComposer: url: https://github.com/matrix-org/matrix-wysiwyg-composer-swift - version: 0.22.0 + version: 1.1.0 DeviceKit: url: https://github.com/devicekit/DeviceKit majorVersion: 4.7.0