Merge pull request #7317 from vector-im/aringenbach/7316_indentation_support

Labs: Rich text editor: enable list items indentation
This commit is contained in:
aringenbach 2023-02-01 09:44:45 +01:00 committed by GitHub
commit 2aaef072e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 81 additions and 132 deletions

View file

@ -53,8 +53,6 @@ end
def import_MatrixKit_pods def import_MatrixKit_pods
pod 'libPhoneNumber-iOS', '~> 0.9.13' pod 'libPhoneNumber-iOS', '~> 0.9.13'
pod 'DTCoreText', '~> 1.6.25'
#pod 'DTCoreText/Extension', '~> 1.6.25'
pod 'Down', '~> 0.11.0' pod 'Down', '~> 0.11.0'
end end

View file

@ -9,6 +9,24 @@
"version" : "4.7.0" "version" : "4.7.0"
} }
}, },
{
"identity" : "dtcoretext",
"kind" : "remoteSourceControl",
"location" : "https://github.com/Cocoanetics/DTCoreText",
"state" : {
"revision" : "9d2d4d2296e5d2d852a7d3c592b817d913a5d020",
"version" : "1.6.27"
}
},
{
"identity" : "dtfoundation",
"kind" : "remoteSourceControl",
"location" : "https://github.com/Cocoanetics/DTFoundation.git",
"state" : {
"revision" : "76062513434421cb6c8a1ae1d4f8368a7ebc2da3",
"version" : "1.7.18"
}
},
{ {
"identity" : "maplibre-gl-native-distribution", "identity" : "maplibre-gl-native-distribution",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
@ -23,8 +41,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift", "location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift",
"state" : { "state" : {
"revision" : "6927cb878376136c4a03d919b689af8dfbdad080", "revision" : "3f72aeab7d7e04b52ff3f735ab79a75993f97ef2",
"version" : "0.19.0" "version" : "0.22.0"
} }
}, },
{ {

View file

@ -2582,8 +2582,8 @@ To enable access, tap Settings> Location and select Always";
"wysiwyg_composer_format_action_ordered_list" = "Toggle numbered list"; "wysiwyg_composer_format_action_ordered_list" = "Toggle numbered list";
"wysiwyg_composer_format_action_code_block" = "Toggle code block"; "wysiwyg_composer_format_action_code_block" = "Toggle code block";
"wysiwyg_composer_format_action_quote" = "Toggle quote"; "wysiwyg_composer_format_action_quote" = "Toggle quote";
"wysiwyg_composer_format_action_indent" = "Increase indentation";
"wysiwyg_composer_format_action_un_indent" = "Decrease indentation";
// Links // Links
"wysiwyg_composer_link_action_text" = "Text"; "wysiwyg_composer_link_action_text" = "Text";

View file

@ -9415,6 +9415,10 @@ public class VectorL10n: NSObject {
public static var wysiwygComposerFormatActionCodeBlock: String { public static var wysiwygComposerFormatActionCodeBlock: String {
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_code_block") return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_code_block")
} }
/// Increase indentation
public static var wysiwygComposerFormatActionIndent: String {
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_indent")
}
/// Apply inline code format /// Apply inline code format
public static var wysiwygComposerFormatActionInlineCode: String { public static var wysiwygComposerFormatActionInlineCode: String {
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_inline_code") return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_inline_code")
@ -9439,6 +9443,10 @@ public class VectorL10n: NSObject {
public static var wysiwygComposerFormatActionStrikethrough: String { public static var wysiwygComposerFormatActionStrikethrough: String {
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_strikethrough") return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_strikethrough")
} }
/// Decrease indentation
public static var wysiwygComposerFormatActionUnIndent: String {
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_un_indent")
}
/// Apply strikethrough format /// Apply strikethrough format
public static var wysiwygComposerFormatActionUnderline: String { public static var wysiwygComposerFormatActionUnderline: String {
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_underline") return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_underline")

View file

@ -47,9 +47,7 @@ class HTMLFormatter: NSObject {
var options: [AnyHashable: Any] = [ var options: [AnyHashable: Any] = [
DTUseiOS6Attributes: true, DTUseiOS6Attributes: true,
DTDefaultFontFamily: font.familyName, DTDefaultFontDescriptor: font.fontDescriptor,
DTDefaultFontName: font.fontName,
DTDefaultFontSize: font.pointSize,
DTDefaultLinkDecoration: false, DTDefaultLinkDecoration: false,
DTDefaultLinkColor: ThemeService.shared().theme.colors.links, DTDefaultLinkColor: ThemeService.shared().theme.colors.links,
DTWillFlushBlockCallBack: sanitizeCallback DTWillFlushBlockCallBack: sanitizeCallback

View file

@ -17,6 +17,7 @@
import Foundation import Foundation
import Reusable import Reusable
import WysiwygComposer import WysiwygComposer
import HTMLParser
import SwiftUI import SwiftUI
import Combine import Combine
import UIKit import UIKit
@ -43,9 +44,14 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
private var voiceMessageBottomConstraint: NSLayoutConstraint? private var voiceMessageBottomConstraint: NSLayoutConstraint?
private var hostingViewController: VectorHostingController! private var hostingViewController: VectorHostingController!
private var wysiwygViewModel = WysiwygComposerViewModel( private var wysiwygViewModel = WysiwygComposerViewModel(
textColor: ThemeService.shared().theme.colors.primaryContent, parserStyle: HTMLParserStyle(textColor: ThemeService.shared().theme.colors.primaryContent,
linkColor: ThemeService.shared().theme.colors.links, linkColor: ThemeService.shared().theme.colors.links,
codeBackgroundColor: ThemeService.shared().theme.selectedBackgroundColor 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)
) )
private var viewModel: ComposerViewModelProtocol! private var viewModel: ComposerViewModelProtocol!
@ -298,9 +304,14 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
private func update(theme: Theme) { private func update(theme: Theme) {
hostingViewController.view.backgroundColor = theme.colors.background hostingViewController.view.backgroundColor = theme.colors.background
wysiwygViewModel.textColor = theme.colors.primaryContent wysiwygViewModel.parserStyle = HTMLParserStyle(textColor: ThemeService.shared().theme.colors.primaryContent,
wysiwygViewModel.linkColor = theme.colors.links linkColor: ThemeService.shared().theme.colors.links,
wysiwygViewModel.codeBackgroundColor = theme.selectedBackgroundColor 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)
} }
private func updateTextViewHeight() { private func updateTextViewHeight() {

View file

@ -1,30 +0,0 @@
/*
Copyright 2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
@import Foundation;
#import "EventFormatter.h"
NS_ASSUME_NONNULL_BEGIN
@interface EventFormatter(DTCoreTextFix)
// Fix DTCoreText iOS 13 issue (https://github.com/Cocoanetics/DTCoreText/issues/1168)
+ (void)fixDTCoreTextFont;
@end
NS_ASSUME_NONNULL_END

View file

@ -1,80 +0,0 @@
/*
Copyright 2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import "EventFormatter+DTCoreTextFix.h"
@import UIKit;
@import CoreText;
@import ObjectiveC;
#pragma mark - UIFont DTCoreText fix
@interface UIFont (vc_DTCoreTextFix)
+ (UIFont *)vc_fixedFontWithCTFont:(CTFontRef)ctFont;
@end
@implementation UIFont (vc_DTCoreTextFix)
+ (UIFont *)vc_fixedFontWithCTFont:(CTFontRef)ctFont {
NSString *fontName = (__bridge_transfer NSString *)CTFontCopyName(ctFont, kCTFontPostScriptNameKey);
CGFloat fontSize = CTFontGetSize(ctFont);
UIFont *font = [UIFont fontWithName:fontName size:fontSize];
// On iOS 13+ "TimesNewRomanPSMT" will be used instead of "SFUI"
// In case of "Times New Roman" fallback, use system font and reuse UIFontDescriptorSymbolicTraits.
if ([font.familyName.lowercaseString containsString:@"times"])
{
UIFontDescriptorSymbolicTraits symbolicTraits = (UIFontDescriptorSymbolicTraits)CTFontGetSymbolicTraits(ctFont);
UIFontDescriptor *systemFontDescriptor = [UIFont systemFontOfSize:fontSize].fontDescriptor;
UIFontDescriptor *finalFontDescriptor = [systemFontDescriptor fontDescriptorWithSymbolicTraits:symbolicTraits];
font = [UIFont fontWithDescriptor:finalFontDescriptor size:fontSize];
}
return font;
}
@end
#pragma mark - Implementation
@implementation EventFormatter(DTCoreTextFix)
// DTCoreText iOS 13 fix. See issue and comment here: https://github.com/Cocoanetics/DTCoreText/issues/1168#issuecomment-583541514
+ (void)fixDTCoreTextFont
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class originalClass = object_getClass([UIFont class]);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
SEL originalSelector = @selector(fontWithCTFont:); // DTCoreText method we're overriding
SEL ourSelector = @selector(vc_fixedFontWithCTFont:); // Use custom implementation
#pragma clang diagnostic pop
Method originalMethod = class_getClassMethod(originalClass, originalSelector);
Method swizzledMethod = class_getClassMethod(originalClass, ourSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
});
}
@end

View file

@ -25,7 +25,6 @@
#import "MXDecryptionResult.h" #import "MXDecryptionResult.h"
#import "DecryptionFailureTracker.h" #import "DecryptionFailureTracker.h"
#import "EventFormatter+DTCoreTextFix.h"
#import <MatrixSDK/MatrixSDK.h> #import <MatrixSDK/MatrixSDK.h>
#pragma mark - Constants definitions #pragma mark - Constants definitions
@ -50,11 +49,6 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
@implementation EventFormatter @implementation EventFormatter
+ (void)load
{
[self fixDTCoreTextFont];
}
- (void)initDateTimeFormatters - (void)initDateTimeFormatters
{ {
[super initDateTimeFormatters]; [super initDateTimeFormatters];

View file

@ -44,6 +44,7 @@ targets:
- package: SwiftOGG - package: SwiftOGG
- package: WysiwygComposer - package: WysiwygComposer
- package: DeviceKit - package: DeviceKit
- package: DTCoreText
configFiles: configFiles:
Debug: Debug.xcconfig Debug: Debug.xcconfig

View file

@ -33,6 +33,7 @@ targets:
dependencies: dependencies:
- package: DeviceKit - package: DeviceKit
- package: DTCoreText
configFiles: configFiles:
Debug: Debug.xcconfig Debug: Debug.xcconfig

View file

@ -33,6 +33,7 @@ targets:
dependencies: dependencies:
- package: DeviceKit - package: DeviceKit
- package: DTCoreText
configFiles: configFiles:
Debug: Debug.xcconfig Debug: Debug.xcconfig

View file

@ -36,6 +36,8 @@ enum FormatType {
case strikethrough case strikethrough
case unorderedList case unorderedList
case orderedList case orderedList
case indent
case unIndent
case inlineCode case inlineCode
case codeBlock case codeBlock
case quote case quote
@ -66,6 +68,10 @@ extension FormatItem {
return Asset.Images.bulletList.name return Asset.Images.bulletList.name
case .orderedList: case .orderedList:
return Asset.Images.numberedList.name return Asset.Images.numberedList.name
case .indent:
return Asset.Images.indentIncrease.name
case .unIndent:
return Asset.Images.indentDecrease.name
case .inlineCode: case .inlineCode:
return Asset.Images.code.name return Asset.Images.code.name
case .codeBlock: case .codeBlock:
@ -91,6 +97,10 @@ extension FormatItem {
return "unorderedListButton" return "unorderedListButton"
case .orderedList: case .orderedList:
return "orderedListButton" return "orderedListButton"
case .indent:
return "indentListButton"
case .unIndent:
return "unIndentButton"
case .inlineCode: case .inlineCode:
return "inlineCodeButton" return "inlineCodeButton"
case .codeBlock: case .codeBlock:
@ -116,6 +126,10 @@ extension FormatItem {
return VectorL10n.wysiwygComposerFormatActionUnorderedList return VectorL10n.wysiwygComposerFormatActionUnorderedList
case .orderedList: case .orderedList:
return VectorL10n.wysiwygComposerFormatActionOrderedList return VectorL10n.wysiwygComposerFormatActionOrderedList
case .indent:
return VectorL10n.wysiwygComposerFormatActionIndent
case .unIndent:
return VectorL10n.wysiwygComposerFormatActionUnIndent
case .inlineCode: case .inlineCode:
return VectorL10n.wysiwygComposerFormatActionInlineCode return VectorL10n.wysiwygComposerFormatActionInlineCode
case .codeBlock: case .codeBlock:
@ -144,6 +158,10 @@ extension FormatType {
return .unorderedList return .unorderedList
case .orderedList: case .orderedList:
return .orderedList return .orderedList
case .indent:
return .indent
case .unIndent:
return .unIndent
case .inlineCode: case .inlineCode:
return .inlineCode return .inlineCode
case .codeBlock: case .codeBlock:
@ -171,6 +189,10 @@ extension FormatType {
return .unorderedList return .unorderedList
case .orderedList: case .orderedList:
return .orderedList return .orderedList
case .indent:
return .indent
case .unIndent:
return .unIndent
case .inlineCode: case .inlineCode:
return .inlineCode return .inlineCode
case .codeBlock: case .codeBlock:

View file

@ -34,6 +34,7 @@ targets:
dependencies: dependencies:
- sdk: Intents.framework - sdk: Intents.framework
- package: DeviceKit - package: DeviceKit
- package: DTCoreText
configFiles: configFiles:
Debug: Debug.xcconfig Debug: Debug.xcconfig

1
changelog.d/7316.change Normal file
View file

@ -0,0 +1 @@
Labs: Rich text editor: enable list items indentation

View file

@ -259,6 +259,8 @@ platform :ios do
# Generate xcodebuild additional arguments # Generate xcodebuild additional arguments
xcargs_hash = { xcargs_hash = {
"GCC_PREPROCESSOR_DEFINITIONS" => "$(GCC_PREPROCESSOR_DEFINITIONS) #{additional_preprocessor_definitions}", "GCC_PREPROCESSOR_DEFINITIONS" => "$(GCC_PREPROCESSOR_DEFINITIONS) #{additional_preprocessor_definitions}",
# Fix XCode 14 code signing issues for Swift packages containing resources bundles.
"CODE_SIGN_STYLE" => "Manual",
} }
xcargs = xcargs_hash.map { |k, v| "#{k}=#{v.shellescape}" }.join(" ") xcargs = xcargs_hash.map { |k, v| "#{k}=#{v.shellescape}" }.join(" ")

View file

@ -53,7 +53,10 @@ packages:
branch: main branch: main
WysiwygComposer: WysiwygComposer:
url: https://github.com/matrix-org/matrix-wysiwyg-composer-swift url: https://github.com/matrix-org/matrix-wysiwyg-composer-swift
version: 0.19.0 version: 0.22.0
DeviceKit: DeviceKit:
url: https://github.com/devicekit/DeviceKit url: https://github.com/devicekit/DeviceKit
majorVersion: 4.7.0 majorVersion: 4.7.0
DTCoreText:
url: https://github.com/Cocoanetics/DTCoreText
version: 1.6.27