Skip to content

Commit

Permalink
Add link and image button selection and enabled states, formatter cle…
Browse files Browse the repository at this point in the history
…anup
  • Loading branch information
tonisevener committed Jan 5, 2024
1 parent e430cb4 commit 1347073
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,18 @@ class WKEditorToolbarButton: WKComponentView {
set {
button.isSelected = newValue
updateColors()
accessibilityTraits = newValue ? [.button, .selected] : [.button]
accessibilityTraits = button.accessibilityTraits
}
}

var isEnabled: Bool {
get {
return button.isEnabled
}
set {
button.isEnabled = newValue
updateColors()
accessibilityTraits = button.accessibilityTraits
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
@IBOutlet private weak var citationButton: WKEditorToolbarButton!
@IBOutlet private weak var linkButton: WKEditorToolbarButton!
@IBOutlet private weak var templateButton: WKEditorToolbarButton!
@IBOutlet private weak var mediaButton: WKEditorToolbarButton!
@IBOutlet private weak var imageButton: WKEditorToolbarButton!
@IBOutlet private weak var findInPageButton: WKEditorToolbarButton!

@IBOutlet private weak var unorderedListButton: WKEditorToolbarButton!
Expand Down Expand Up @@ -101,9 +101,9 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
templateButton.addTarget(self, action: #selector(tappedTemplate), for: .touchUpInside)
templateButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonTemplate

mediaButton.setImage(WKSFSymbolIcon.for(symbol: .photo), for: .normal)
mediaButton.addTarget(self, action: #selector(tappedMedia), for: .touchUpInside)
mediaButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonMedia
imageButton.setImage(WKSFSymbolIcon.for(symbol: .photo), for: .normal)
imageButton.addTarget(self, action: #selector(tappedMedia), for: .touchUpInside)
imageButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonMedia

findInPageButton.setImage(WKSFSymbolIcon.for(symbol: .docTextMagnifyingGlass), for: .normal)
findInPageButton.addTarget(self, action: #selector(tappedFindInPage), for: .touchUpInside)
Expand Down Expand Up @@ -140,6 +140,7 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {

cursorRightButton.setImage(WKIcon.chevronRight, for: .normal)
cursorRightButton.addTarget(self, action: #selector(tappedCursorRight), for: .touchUpInside)
cursorRightButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCursorRight

NotificationCenter.default.addObserver(self, selector: #selector(updateButtonSelectionState(_:)), name: Notification.WKSourceEditorSelectionState, object: nil)
}
Expand All @@ -152,7 +153,8 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
}

templateButton.isSelected = selectionState.isHorizontalTemplate
cursorRightButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCursorRight
linkButton.isSelected = selectionState.isSimpleLink
imageButton.isEnabled = !selectionState.isBold && !selectionState.isItalics && !selectionState.isSimpleLink
}

// MARK: - Button Actions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina5_9" orientation="landscape" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="Stack View standard spacing" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
Expand Down Expand Up @@ -281,11 +281,11 @@
<outlet property="findInPageButton" destination="ysd-bl-nOt" id="YnS-6B-WJp"/>
<outlet property="formatHeadingButton" destination="7QK-zM-3Zu" id="OVa-3o-cP2"/>
<outlet property="formatTextButton" destination="q5y-cw-4pq" id="EVV-8g-wME"/>
<outlet property="imageButton" destination="Oyz-BA-g0g" id="Gxu-b5-3Sp"/>
<outlet property="increaseIndentionButton" destination="YcQ-k6-ZuB" id="phQ-vm-eKH"/>
<outlet property="linkButton" destination="lOp-Bv-UED" id="I7F-zV-jom"/>
<outlet property="mediaButton" destination="Oyz-BA-g0g" id="Gxu-b5-3Sp"/>
<outlet property="primaryContainerView" destination="BWO-2h-I64" id="8BW-Xe-ftH"/>
<outlet property="orderedListButton" destination="Usg-R3-2O9" id="8Qf-xg-gjD"/>
<outlet property="primaryContainerView" destination="BWO-2h-I64" id="8BW-Xe-ftH"/>
<outlet property="scrollView" destination="ZnR-ux-s6T" id="cvF-Ya-s9R"/>
<outlet property="secondaryContainerView" destination="51i-1d-Lli" id="RSM-Cp-gEO"/>
<outlet property="stackView" destination="ajR-7a-Sik" id="xc8-7a-mMJ"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class WKEditorToolbarHighlightView: WKEditorToolbarView {
boldButton.isSelected = selectionState.isBold
italicsButton.isSelected = selectionState.isItalics
templateButton.isSelected = selectionState.isHorizontalTemplate
linkButton.isSelected = selectionState.isSimpleLink
}

// MARK: - Button Actions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class WKEditorToolbarPlainView: WKEditorToolbarView {
boldButton.isSelected = selectionState.isBold
italicsButton.isSelected = selectionState.isItalics
templateButton.isSelected = selectionState.isHorizontalTemplate
linkButton.isSelected = selectionState.isSimpleLink
}

// MARK: Button Actions
Expand Down
166 changes: 65 additions & 101 deletions Components/Sources/ComponentsObjC/WKSourceEditorFormatterLink.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@

@interface WKSourceEditorFormatterLink ()

@property (nonatomic, strong) NSDictionary *simpleLinkMarkupAttributes;
@property (nonatomic, strong) NSDictionary *simpleLinkContentAttributes;
@property (nonatomic, strong) NSDictionary *linkWithNestedLinkMarkupAndContentAttributes;
@property (nonatomic, strong) NSDictionary *simpleLinkAttributes;
@property (nonatomic, strong) NSDictionary *linkWithNestedLinkAttributes;
@property (nonatomic, strong) NSRegularExpression *simpleLinkRegex;
@property (nonatomic, strong) NSRegularExpression *linkWithNestedLinkRegex;

Expand All @@ -14,9 +13,8 @@ @interface WKSourceEditorFormatterLink ()
#pragma mark - Custom Attributed String Keys

NSString * const WKSourceEditorCustomKeyColorBlue = @"WKSourceEditorCustomKeyColorBlue";
NSString * const WKSourceEditorCustomKeyMarkupLink = @"WKSourceEditorCustomKeyMarkupLink";
NSString * const WKSourceEditorCustomKeyContentLink = @"WKSourceEditorCustomKeyContentLink";
NSString * const WKSourceEditorCustomKeyMarkupAndContentLinkWithNestedLink = @"WKSourceEditorCustomKeyMarkupAndContentLinkWithNestedLink";
NSString * const WKSourceEditorCustomKeyLink = @"WKSourceEditorCustomKeyLink";
NSString * const WKSourceEditorCustomKeyLinkWithNestedLink = @"WKSourceEditorCustomKeyLinkWithNestedLink";

@implementation WKSourceEditorFormatterLink

Expand All @@ -25,22 +23,16 @@ @implementation WKSourceEditorFormatterLink
- (instancetype)initWithColors:(nonnull WKSourceEditorColors *)colors fonts:(nonnull WKSourceEditorFonts *)fonts {
self = [super initWithColors:colors fonts:fonts];
if (self) {
_simpleLinkMarkupAttributes = @{
WKSourceEditorCustomKeyMarkupLink: [NSNumber numberWithBool:YES],
NSForegroundColorAttributeName: colors.blueForegroundColor,
WKSourceEditorCustomKeyColorBlue: [NSNumber numberWithBool:YES]
};

_simpleLinkContentAttributes = @{
WKSourceEditorCustomKeyContentLink: [NSNumber numberWithBool:YES],
_simpleLinkAttributes = @{
WKSourceEditorCustomKeyLink: [NSNumber numberWithBool:YES],
NSForegroundColorAttributeName: colors.blueForegroundColor,
WKSourceEditorCustomKeyColorBlue: [NSNumber numberWithBool:YES]
};

_simpleLinkRegex = [[NSRegularExpression alloc] initWithPattern:@"(\\[{2})([^\\[\\]\\n]*)(\\]{2})" options:0 error:nil];

_linkWithNestedLinkMarkupAndContentAttributes = @{
WKSourceEditorCustomKeyMarkupAndContentLinkWithNestedLink: [NSNumber numberWithBool:YES],
_linkWithNestedLinkAttributes = @{
WKSourceEditorCustomKeyLinkWithNestedLink: [NSNumber numberWithBool:YES],
NSForegroundColorAttributeName: colors.blueForegroundColor,
WKSourceEditorCustomKeyColorBlue: [NSNumber numberWithBool:YES]
};
Expand All @@ -57,8 +49,8 @@ - (void)addSyntaxHighlightingToAttributedString:(nonnull NSMutableAttributedStri

// Reset
[attributedString removeAttribute:WKSourceEditorCustomKeyColorBlue range:range];
[attributedString removeAttribute:WKSourceEditorCustomKeyContentLink range:range];
[attributedString removeAttribute:WKSourceEditorCustomKeyMarkupAndContentLinkWithNestedLink range:range];
[attributedString removeAttribute:WKSourceEditorCustomKeyLink range:range];
[attributedString removeAttribute:WKSourceEditorCustomKeyLinkWithNestedLink range:range];

// This section finds and highlights simple links that do NOT contain nested links, e.g. [[Cat]] and [[Dog|puppy]].
[self.simpleLinkRegex enumerateMatchesInString:attributedString.string
Expand All @@ -71,15 +63,15 @@ - (void)addSyntaxHighlightingToAttributedString:(nonnull NSMutableAttributedStri
NSRange closingRange = [result rangeAtIndex:3];

if (openingRange.location != NSNotFound) {
[attributedString addAttributes:self.simpleLinkMarkupAttributes range:openingRange];
[attributedString addAttributes:self.simpleLinkAttributes range:openingRange];
}

if (contentRange.location != NSNotFound) {
[attributedString addAttributes:self.simpleLinkContentAttributes range:contentRange];
[attributedString addAttributes:self.simpleLinkAttributes range:contentRange];
}

if (closingRange.location != NSNotFound) {
[attributedString addAttributes:self.simpleLinkMarkupAttributes range:closingRange];
[attributedString addAttributes:self.simpleLinkAttributes range:closingRange];
}
}];

Expand All @@ -99,7 +91,7 @@ - (void)addSyntaxHighlightingToAttributedString:(nonnull NSMutableAttributedStri
for (NSValue *value in linkWithNestedLinkRanges) {
NSRange range = [value rangeValue];
if (range.location != NSNotFound) {
[attributedString addAttributes:self.linkWithNestedLinkMarkupAndContentAttributes range:range];
[attributedString addAttributes:self.linkWithNestedLinkAttributes range:range];
}
}
}
Expand All @@ -108,17 +100,13 @@ - (void)addSyntaxHighlightingToAttributedString:(nonnull NSMutableAttributedStri

- (void)updateColors:(WKSourceEditorColors *)colors inAttributedString:(NSMutableAttributedString *)attributedString inRange:(NSRange)range {

NSMutableDictionary *mutSimpleLinkMarkupAttributes = [[NSMutableDictionary alloc] initWithDictionary:self.simpleLinkMarkupAttributes];
[mutSimpleLinkMarkupAttributes setObject:colors.blueForegroundColor forKey:NSForegroundColorAttributeName];
self.simpleLinkMarkupAttributes = [[NSDictionary alloc] initWithDictionary:mutSimpleLinkMarkupAttributes];

NSMutableDictionary *mutSimpleLinkContentAttributes = [[NSMutableDictionary alloc] initWithDictionary:self.simpleLinkContentAttributes];
[mutSimpleLinkContentAttributes setObject:colors.blueForegroundColor forKey:NSForegroundColorAttributeName];
self.simpleLinkContentAttributes = [[NSDictionary alloc] initWithDictionary:mutSimpleLinkContentAttributes];
NSMutableDictionary *mutSimpleLinkAttributes = [[NSMutableDictionary alloc] initWithDictionary:self.simpleLinkAttributes];
[mutSimpleLinkAttributes setObject:colors.blueForegroundColor forKey:NSForegroundColorAttributeName];
self.simpleLinkAttributes = [[NSDictionary alloc] initWithDictionary:mutSimpleLinkAttributes];

NSMutableDictionary *mutLinkWithNestedLinkMarkupAndContentAttributes = [[NSMutableDictionary alloc] initWithDictionary:self.linkWithNestedLinkMarkupAndContentAttributes];
[mutLinkWithNestedLinkMarkupAndContentAttributes setObject:colors.blueForegroundColor forKey:NSForegroundColorAttributeName];
self.linkWithNestedLinkMarkupAndContentAttributes = [[NSDictionary alloc] initWithDictionary:mutLinkWithNestedLinkMarkupAndContentAttributes];
NSMutableDictionary *mutLinkWithNestedLinkAttributes = [[NSMutableDictionary alloc] initWithDictionary:self.linkWithNestedLinkAttributes];
[mutLinkWithNestedLinkAttributes setObject:colors.blueForegroundColor forKey:NSForegroundColorAttributeName];
self.linkWithNestedLinkAttributes = [[NSDictionary alloc] initWithDictionary:mutLinkWithNestedLinkAttributes];

[attributedString enumerateAttribute:WKSourceEditorCustomKeyColorBlue
inRange:range
Expand All @@ -140,79 +128,12 @@ - (void)updateFonts:(WKSourceEditorFonts *)fonts inAttributedString:(NSMutableAt
#pragma mark - Public

- (BOOL)attributedString:(NSMutableAttributedString *)attributedString isSimpleLinkInRange:(NSRange)range {
__block BOOL isContentKey = NO;
if (range.length == 0) {

if (attributedString.length > range.location) {
NSDictionary<NSAttributedStringKey,id> *attrs = [attributedString attributesAtIndex:range.location effectiveRange:nil];

if (attrs[WKSourceEditorCustomKeyContentLink] != nil) {
isContentKey = YES;
} else {
// Edge case, check previous character if we are up against closing markup
if (attrs[WKSourceEditorCustomKeyMarkupLink]) {
attrs = [attributedString attributesAtIndex:range.location - 1 effectiveRange:nil];
if (attrs[WKSourceEditorCustomKeyContentLink] != nil) {
isContentKey = YES;
}
}
}
}

} else {
__block NSRange unionRange = NSMakeRange(NSNotFound, 0);
[attributedString enumerateAttributesInRange:range options:nil usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange loopRange, BOOL * _Nonnull stop) {
if (attrs[WKSourceEditorCustomKeyContentLink] != nil) {
if (unionRange.location == NSNotFound) {
unionRange = loopRange;
} else {
unionRange = NSUnionRange(unionRange, loopRange);
}
stop = YES;
}
}];

if (NSEqualRanges(unionRange, range)) {
isContentKey = YES;
}
}

return isContentKey;
return [self attributedString:attributedString isKey:WKSourceEditorCustomKeyLink inRange:range];
}

- (BOOL)attributedString:(NSMutableAttributedString *)attributedString isLinkWithNestedLinkInRange:(NSRange)range {

__block BOOL isKey = NO;
if (range.length == 0) {

if (attributedString.length > range.location) {
NSDictionary<NSAttributedStringKey,id> *attrs = [attributedString attributesAtIndex:range.location effectiveRange:nil];

if (attrs[WKSourceEditorCustomKeyMarkupAndContentLinkWithNestedLink] != nil) {
isKey = YES;
}
}

} else {
__block NSRange unionRange = NSMakeRange(NSNotFound, 0);
[attributedString enumerateAttributesInRange:range options:nil usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange loopRange, BOOL * _Nonnull stop) {
if (attrs[WKSourceEditorCustomKeyMarkupAndContentLinkWithNestedLink] != nil) {
if (unionRange.location == NSNotFound) {
unionRange = loopRange;
} else {
unionRange = NSUnionRange(unionRange, loopRange);
}
stop = YES;
}
}];

if (NSEqualRanges(unionRange, range)) {
isKey = YES;
}
}

return isKey;

return [self attributedString:attributedString isKey:WKSourceEditorCustomKeyLinkWithNestedLink inRange:range];
}

#pragma mark - Private
Expand Down Expand Up @@ -276,4 +197,47 @@ - (NSArray *)linkWithNestedLinkRangesInString: (NSString *)string startingIndex:
return [[NSArray alloc] initWithArray:completedLinkWithNestedLinkRanges];
}

- (BOOL)attributedString:(NSMutableAttributedString *)attributedString isKey:(NSString *)key inRange:(NSRange)range {
__block BOOL isKey = NO;
if (range.length == 0) {

if (attributedString.length > range.location) {
NSDictionary<NSAttributedStringKey,id> *attrs = [attributedString attributesAtIndex:range.location effectiveRange:nil];

if (attrs[key] != nil) {
isKey = YES;
}

// Edge case, check previous character if we are up against opening markup
if (attrs[WKSourceEditorCustomKeyLink]) {
if (attributedString.length > range.location - 1) {
attrs = [attributedString attributesAtIndex:range.location - 1 effectiveRange:nil];
if (attrs[key] == nil) {
isKey = NO;
}
}
}
}

} else {
__block NSRange unionRange = NSMakeRange(NSNotFound, 0);
[attributedString enumerateAttributesInRange:range options:nil usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange loopRange, BOOL * _Nonnull stop) {
if (attrs[key] != nil) {
if (unionRange.location == NSNotFound) {
unionRange = loopRange;
} else {
unionRange = NSUnionRange(unionRange, loopRange);
}
stop = YES;
}
}];

if (NSEqualRanges(unionRange, range)) {
isKey = YES;
}
}

return isKey;
}

@end

0 comments on commit 1347073

Please sign in to comment.