diff --git a/.travis.yml b/.travis.yml index 4554f82..e48951d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -osx_image: xcode8.2 +osx_image: xcode9 language: objective-c notifications: email: true diff --git a/Assets/WPEditorFormatbarView.xib b/Assets/WPEditorFormatbarView.xib index d52483a..b6ca652 100644 --- a/Assets/WPEditorFormatbarView.xib +++ b/Assets/WPEditorFormatbarView.xib @@ -1,18 +1,22 @@ - - + + + + + - + + + - - + + - - + @@ -38,16 +42,14 @@ - - + - - + @@ -68,10 +70,9 @@ - - - - + + + @@ -85,24 +86,22 @@ - - + - - + - - - + + + @@ -120,18 +119,18 @@ - - - - - - - - + + + + + + + + @@ -140,12 +139,12 @@ - + + + - - @@ -154,13 +153,12 @@ + + + - - - - @@ -182,6 +180,7 @@ + diff --git a/Classes/HRColorPickerViewController.h b/Classes/HRColorPickerViewController.h index 71f8522..fdb3c84 100755 --- a/Classes/HRColorPickerViewController.h +++ b/Classes/HRColorPickerViewController.h @@ -66,8 +66,10 @@ typedef enum { */ - (id)initWithColor:(UIColor*)defaultColor fullColor:(BOOL)fullColor saveStyle:(HCPCSaveStyle)saveStyle; -/** @deprecated use -save: instead of this . */ -- (void)saveColor:(id)sender; +/** + * @deprecated use -save: instead of this. + */ +- (void)saveColor:(id)sender __attribute__((deprecated)); - (void)save; - (void)save:(id)sender; diff --git a/Classes/WPEditorField.h b/Classes/WPEditorField.h index 1da3a91..c5e551f 100644 --- a/Classes/WPEditorField.h +++ b/Classes/WPEditorField.h @@ -18,7 +18,7 @@ * @brief Initializes the field with the specified HTML node id. * * @param nodeId The id of the html node this object will wrap. Cannot be nil. - * @param webVieq The web view to use for all javascript calls. Cannot be nil. + * @param webView The web view to use for all javascript calls. Cannot be nil. * * @returns The initialized object. */ @@ -87,7 +87,7 @@ /** * @brief Sets the placeholder color for this field. * - * @param placeholderText The new placeholder color. + * @param placeholderColor The new placeholder color. */ - (void)setPlaceholderColor:(UIColor *)placeholderColor; diff --git a/Classes/WPEditorField.m b/Classes/WPEditorField.m index 1221ea5..abd4bb6 100644 --- a/Classes/WPEditorField.m +++ b/Classes/WPEditorField.m @@ -169,7 +169,7 @@ - (void)setText:(NSString*)text } else { if (text) { - text = [self addSlashes:text]; + text = [self sanitizeHTML:text]; } else { text = @""; } @@ -187,7 +187,7 @@ - (void)setHtml:(NSString*)html } else { if (html) { - html = [self addSlashes:html]; + html = [self sanitizeHTML:html]; } else { html = @""; } @@ -205,7 +205,7 @@ - (void)setPlaceholderText:(NSString*)placeholderText if (!self.domLoaded) { self.preloadedPlaceholderText = placeholderText; } else { - placeholderText = [self addSlashes:placeholderText]; + placeholderText = [self sanitizeHTML:placeholderText]; NSString* javascript = [NSString stringWithFormat:@"%@.setPlaceholderText(\"%@\");", [self wrappedNodeJavascriptAccessor], placeholderText]; [self.webView stringByEvaluatingJavaScriptFromString:javascript]; @@ -232,15 +232,18 @@ - (void)setPlaceholderColor:(UIColor *)placeholderColor #pragma mark - URL & HTML utilities /** - * @brief Adds slashes to the specified HTML string, to prevent injections when calling JS + * @brief Adds slashes and removes script tags from the specified HTML string, to prevent injections when calling JS * code. * - * @param html The HTML string to add slashes to. Cannot be nil. + * @param html The HTML string to sanitize. Cannot be nil. * - * @returns The HTML string with the added slashes. + * @returns The sanitized HTML string. */ -- (NSString *)addSlashes:(NSString *)html +- (NSString *)sanitizeHTML:(NSString *)html { + html = [html stringByReplacingOccurrencesOfString:@"—" withString:@"--"]; + html = [html stringByReplacingOccurrencesOfString:@"“" withString:@"\""]; + html = [html stringByReplacingOccurrencesOfString:@"”" withString:@"\""]; html = [html stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; html = [html stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; html = [html stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; @@ -252,6 +255,9 @@ - (NSString *)addSlashes:(NSString *)html html = [html stringByReplacingOccurrencesOfString:@"\u2028" withString:@"\\u2028"]; html = [html stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\\u2029"]; + html = [html stringByReplacingOccurrencesOfString:@"" withString:@"</script>" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [html length])]; + return html; } diff --git a/Classes/WPEditorFormatbarView.h b/Classes/WPEditorFormatbarView.h index 2a2441e..9a6d814 100644 --- a/Classes/WPEditorFormatbarView.h +++ b/Classes/WPEditorFormatbarView.h @@ -3,6 +3,8 @@ @class WPEditorFormatbarView; @class ZSSBarButtonItem; +extern const CGFloat WPEditorFormatbarViewToolbarHeight; + typedef enum { kWPEditorViewControllerElementTagUnknown = -1, @@ -139,6 +141,14 @@ typedef enum #pragma mark - Toolbar items +/** + * @brief Returns a toolbar item (if any) matching the specified tag. + * + * @param tag WPEditorViewControllerElementTag of the item to return. + * @return A toolbar item with the specified tag. + */ +- (UIBarButtonItem *)toolBarItemWithTag:(WPEditorViewControllerElementTag)tag; + /** * @brief Makes a toolbar item visible or hidden * diff --git a/Classes/WPEditorFormatbarView.m b/Classes/WPEditorFormatbarView.m index 463f840..f9fe0ce 100644 --- a/Classes/WPEditorFormatbarView.m +++ b/Classes/WPEditorFormatbarView.m @@ -4,11 +4,14 @@ #import "WPEditorToolbarButton.h" #import "ZSSBarButtonItem.h" +const CGFloat WPEditorFormatbarViewToolbarHeight = 44; + @interface WPEditorFormatbarView () @property (unsafe_unretained, nonatomic) IBOutlet UIToolbar *leftToolbar; @property (unsafe_unretained, nonatomic) IBOutlet UIToolbar *regularToolbar; @property (unsafe_unretained, nonatomic) IBOutlet UIView *horizontalBorder; +@property (unsafe_unretained, nonatomic) IBOutlet NSLayoutConstraint *toolbarBottomConstraint; // Compact size class bar button items @property (unsafe_unretained, nonatomic) IBOutlet ZSSBarButtonItem *imageButton; @@ -92,6 +95,24 @@ - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection DDLogInfo(@"Format bar trait collection did change from: %@", previousTraitCollection); } +- (void)layoutSubviews { + [super layoutSubviews]; + // HACK: Sergio Estevao (2017-10-10): Change the size of the items whe running on a device with a width smaller or equal than 320 (iPhone SE) + if (self.frame.size.width <= 320) { + for (UIBarButtonItem *item in self.leftToolbar.items) { + item.width = roundf(item.image.size.width * 0.75); + } + } +} + +- (void)layoutMarginsDidChange { + [super layoutMarginsDidChange]; + // Sergio Estevao (2017-10-13): On iOS11 we move the contraint to use the safeAreaInsets in order to be safe on iOS11. + if( @available(iOS 11, *)) { + self.toolbarBottomConstraint.constant = -self.safeAreaInsets.bottom; + } +} + #pragma mark - Setters - (void)setBackgroundColor:(UIColor *)backgroundColor @@ -189,6 +210,27 @@ - (void)setSelectedItemTintColor:(UIColor *)selectedItemTintColor #pragma mark - Toolbar items +- (UIBarButtonItem *)toolBarItemWithTag:(WPEditorViewControllerElementTag)tag +{ + // Find whichever toolbar is currently installed in the view hierarchy. + UIToolbar *toolbar; + if (self.leftToolbar.window) { + toolbar = self.leftToolbar; + } else if (self.regularToolbar.window) { + toolbar = self.regularToolbar; + } + + if (toolbar) { + for (ZSSBarButtonItem *item in toolbar.items) { + if (item.tag == tag) { + return item; + } + } + } + + return nil; +} + - (void)toolBarItemWithTag:(WPEditorViewControllerElementTag)tag setVisible:(BOOL)visible { for (ZSSBarButtonItem *item in self.leftToolbar.items) { @@ -329,10 +371,12 @@ - (void)initBarButtonItem:(ZSSBarButtonItem*)barButtonItem customButton.normalTintColor = self.itemTintColor; customButton.selectedTintColor = self.selectedItemTintColor; customButton.disabledTintColor = self.disabledItemTintColor; + customButton.imageView.contentMode = UIViewContentModeScaleAspectFill; [customButton addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside]; barButtonItem.customView = customButton; + barButtonItem.image = image; } - (void)initBlockQuoteBarButton diff --git a/Classes/WPEditorView.h b/Classes/WPEditorView.h index ad7cd67..db8631b 100644 --- a/Classes/WPEditorView.h +++ b/Classes/WPEditorView.h @@ -124,7 +124,7 @@ * @brief Received when the user taps on a video in the editor. * * @param editorView The editor view. - * @param videoId The id of image of the image that was tapped. + * @param videoID The id of image of the image that was tapped. * @param url The url of the image that was tapped. * */ @@ -156,7 +156,7 @@ stylesForCurrentSelection:(NSArray*)styles; * @brief Received when a video local url is replaced by the final remote url. * * @param editorView The editor view. - * @param videoId The unique id of the video that had the local url replaced by remote url. + * @param videoID The unique id of the video that had the local url replaced by remote url. * */ - (void)editorView:(WPEditorView*)editorView @@ -166,7 +166,7 @@ stylesForCurrentSelection:(NSArray*)styles; * @brief Received when an image is pasted into the editor. * * @param editorView The editor view. - * @param imageId The id of image of the image that was pasted. + * @param image The image that was pasted. * */ - (void)editorView:(WPEditorView*)editorView diff --git a/Classes/WPEditorView.m b/Classes/WPEditorView.m index f67d838..d909fcc 100644 --- a/Classes/WPEditorView.m +++ b/Classes/WPEditorView.m @@ -15,7 +15,7 @@ #import "ZSSTextView.h" typedef void(^WPEditorViewCallbackParameterProcessingBlock)(NSString* parameterName, NSString* parameterValue); -typedef void(^WPEditorViewNoParamsCompletionBlock)(); +typedef void(^WPEditorViewNoParamsCompletionBlock)(void); static NSString* const kDefaultCallbackParameterSeparator = @"~"; static NSString* const kDefaultCallbackParameterComponentSeparator = @"="; @@ -108,6 +108,33 @@ - (void)willMoveToSuperview:(UIView *)newSuperview } } +- (void)layoutSubviews +{ + [super layoutSubviews]; + + UIEdgeInsets insets = UIEdgeInsetsZero; + if (@available(iOS 11, *)) { + insets = self.safeAreaInsets; + } + + CGRect frame = self.bounds; + CGFloat textWidth = CGRectGetWidth(frame) - (2 * UITextFieldLeftRightInset) - insets.left - insets.right; + CGRect titleFrame = CGRectMake(UITextFieldLeftRightInset + insets.left, SourceTitleTextFieldYOffset + insets.top, textWidth, UITextFieldFieldHeight); + CGRect dividerFrame = CGRectMake(UITextFieldLeftRightInset + insets.left, CGRectGetMaxY(titleFrame), textWidth, 1.0f); + CGRect sourceViewFrame = CGRectMake(0.0f, + CGRectGetMaxY(dividerFrame), + CGRectGetWidth(frame), + CGRectGetHeight(frame)-CGRectGetHeight(titleFrame)-CGRectGetHeight(self.sourceContentDividerView.frame)); + self.sourceViewTitleField.frame = titleFrame; + self.sourceContentDividerView.frame = dividerFrame; + self.sourceView.frame = sourceViewFrame; + CGFloat left = UITextFieldLeftRightInset + insets.left; + CGFloat right = UITextFieldLeftRightInset + insets.right; + CGFloat top = HTMLViewTopInset + insets.top; + CGFloat bottom = 0; + self.sourceView.textContainerInset = UIEdgeInsetsMake(top, left, bottom, right); +} + #pragma mark - Init helpers - (void)createSourceTitleViewWithFrame:(CGRect)frame @@ -153,6 +180,10 @@ - (void)createSourceViewWithFrame:(CGRect)frame _sourceView.autoresizesSubviews = YES; _sourceView.textContainerInset = UIEdgeInsetsMake(HTMLViewTopInset, HTMLViewLeftRightInset, 0.0f, HTMLViewLeftRightInset); _sourceView.delegate = self; + if (@available(iOS 11.0, *)) { + _sourceView.smartQuotesType = UITextSmartQuotesTypeNo; + _sourceView.smartDashesType = UITextSmartDashesTypeNo; + } [self addSubview:_sourceView]; } @@ -310,6 +341,19 @@ - (void)keyboardWillShow:(NSNotification *)notification [self refreshKeyboardInsetsWithShowNotification:notification]; } +- (void)refreshInsetsForKeyboardOffset:(CGFloat)vOffset { + UIEdgeInsets insets = UIEdgeInsetsZero; + insets.bottom = vOffset - insets.bottom; + if (@available(iOS 11, *)) { + insets.bottom = insets.bottom - self.safeAreaInsets.bottom; + } + + self.webView.scrollView.contentInset = insets; + self.webView.scrollView.scrollIndicatorInsets = insets; + self.sourceView.contentInset = insets; + self.sourceView.scrollIndicatorInsets = insets; +} + - (void)keyboardWillHide:(NSNotification *)notification { // WORKAROUND: sometimes the input accessory view is not taken into account and a @@ -318,12 +362,7 @@ - (void)keyboardWillHide:(NSNotification *)notification // hiding the keyboard. // CGFloat vOffset = self.sourceView.inputAccessoryView.frame.size.height; - UIEdgeInsets insets = UIEdgeInsetsMake(0.0f, 0.0f, vOffset, 0.0f); - - self.webView.scrollView.contentInset = insets; - self.webView.scrollView.scrollIndicatorInsets = insets; - self.sourceView.contentInset = insets; - self.sourceView.scrollIndicatorInsets = insets; + [self refreshInsetsForKeyboardOffset:vOffset]; } @@ -350,12 +389,7 @@ - (void)refreshKeyboardInsetsWithShowNotification:(NSNotification*)notification CGFloat vOffset = CGRectGetHeight(self.frame) - keyboardOrigin.y; - UIEdgeInsets insets = UIEdgeInsetsMake(0.0f, 0.0f, vOffset, 0.0f); - - self.webView.scrollView.contentInset = insets; - self.webView.scrollView.scrollIndicatorInsets = insets; - self.sourceView.contentInset = insets; - self.sourceView.scrollIndicatorInsets = insets; + [self refreshInsetsForKeyboardOffset:vOffset]; } } @@ -371,7 +405,11 @@ - (void)refreshVisibleViewportAndContentSize NSInteger newHeight = [newHeightString integerValue]; self.lastEditorHeight = newHeight; - self.webView.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.frame), newHeight); + UIEdgeInsets insets = UIEdgeInsetsZero; + if (@available(iOS 11, *)) { + insets = self.safeAreaInsets; + } + self.webView.scrollView.contentSize = CGSizeMake(self.frame.size.width - insets.left - insets.right, newHeight); } #pragma mark - UIWebViewDelegate @@ -680,7 +718,7 @@ - (void)handleVideoTappedCallback:(NSURL *)url /** * @brief Handles a video entered fullscreen callback * - * @param url The url with all the callback information. + * @param aURL The url with all the callback information. */ - (void)handleVideoFullScreenStartedCallback:(NSURL *)aURL { @@ -717,7 +755,7 @@ - (UIView *)findFirstResponder:(UIView *)currentView /** * @brief Handles a video ended fullscreen callback. * - * @param url The url with all the callback information. + * @param aURL The url with all the callback information. */ - (void)handleVideoFullScreenEndedCallback:(NSURL *)aURL { diff --git a/Classes/WPEditorViewController.h b/Classes/WPEditorViewController.h index 8534e98..08a188c 100644 --- a/Classes/WPEditorViewController.h +++ b/Classes/WPEditorViewController.h @@ -31,7 +31,7 @@ WPEditorViewControllerMode; /** * @brief Received when the format bar enabled status has changed. * @param editorController The editor view. - * @param enabled BOOL describing the new state of the format bar + * @param isEnabled BOOL describing the new state of the format bar */ - (void)editorFormatBarStatusChanged:(WPEditorViewController *)editorController enabled:(BOOL)isEnabled; @@ -41,7 +41,7 @@ WPEditorViewControllerMode; * @details The editor fields will be nil before this method is called. This is because editor * fields are created as part of the process of loading the HTML. * - * @param editorView The editor view. + * @param editorViewController The editor view controller. * @param field The new field. */ - (void)editorViewController:(WPEditorViewController*)editorViewController @@ -50,7 +50,7 @@ WPEditorViewControllerMode; /** * @brief Received when the user taps on a image in the editor. * - * @param editorView The editor view. + * @param editorViewController The editor view controller. * @param imageId The id of image of the image that was tapped. * @param url The url of the image that was tapped. * @@ -62,7 +62,7 @@ WPEditorViewControllerMode; /** * @brief Received when the user taps on a image in the editor. * - * @param editorView The editor view. + * @param editorViewController The editor view controller. * @param imageId The id of image of the image that was tapped. * @param url The url of the image that was tapped. * @param imageMeta The parsed meta data about the image. @@ -75,7 +75,7 @@ WPEditorViewControllerMode; /** * @brief Received when the user taps on a image in the editor. * - * @param editorView The editor view. + * @param editorViewController The editor view controller. * @param videoID The id of the video that was tapped. * @param url The url of the video that was tapped. * @@ -87,7 +87,7 @@ WPEditorViewControllerMode; /** * @brief Received when the local image url is replace by the final image in the editor. * - * @param editorView The editor view. + * @param editorViewController The editor view controller. * @param imageId The id of image of the image that was tapped. */ - (void)editorViewController:(WPEditorViewController*)editorViewController @@ -96,7 +96,7 @@ WPEditorViewControllerMode; /** * @brief Received when the local video url is replace by the final video in the editor. * - * @param editorView The editor view. + * @param editorViewController The editor view controller. * @param videoID The id of video that was tapped. */ - (void)editorViewController:(WPEditorViewController*)editorViewController @@ -106,7 +106,7 @@ WPEditorViewControllerMode; * @brief Received when an image is pasted into the editor. * * @param editorViewController The editor view controller. - * @param imageId The id of image of the image that was pasted. + * @param image The image that was pasted. * */ - (void)editorViewController:(WPEditorViewController*)editorViewController @@ -115,7 +115,7 @@ WPEditorViewControllerMode; /** * @brief Received when the editor requests information about a videopress video. * - * @param editorView The editor view. + * @param editorViewController The editor view controller. * @param videoID The id of video that was tapped. */ - (void)editorViewController:(WPEditorViewController *)editorViewController @@ -124,7 +124,7 @@ WPEditorViewControllerMode; /** * @brief Received when the editor removed an uploading media. * - * @param editorView The editor view. + * @param editorViewController The editor view controller. * @param mediaID The id of the media that was removed. */ - (void)editorViewController:(WPEditorViewController *)editorViewController diff --git a/Classes/WPEditorViewController.m b/Classes/WPEditorViewController.m index 6eb78b4..7dec448 100644 --- a/Classes/WPEditorViewController.m +++ b/Classes/WPEditorViewController.m @@ -8,6 +8,43 @@ #import "WPImageMeta.h" #import "ZSSBarButtonItem.h" +@interface WrapperViewForInputView: UIView + @property (nonatomic, strong) WPEditorFormatbarView *toolbar; +@end + +@implementation WrapperViewForInputView + +- (instancetype)initWithToolbar:(WPEditorFormatbarView *)toolbar { + self = [super initWithFrame:CGRectMake(0, 0, self.frame.size.width, WPEditorFormatbarViewToolbarHeight)]; + if (self) { + _toolbar = toolbar; + self.autoresizingMask = UIViewAutoresizingFlexibleHeight; + self.backgroundColor = _toolbar.backgroundColor; + [self addSubview:toolbar]; + self.translatesAutoresizingMaskIntoConstraints = YES; + } + return self; +} + +- (void)safeAreaInsetsDidChange { + [super safeAreaInsetsDidChange]; + [self invalidateIntrinsicContentSize]; +} + +- (void)layoutSubviews { + self.toolbar.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); +} + +- (CGSize)intrinsicContentSize { + UIEdgeInsets insets = UIEdgeInsetsZero; + if(@available(iOS 11, *)){ + insets = self.safeAreaInsets; + } + return CGSizeMake(UIViewNoIntrinsicMetric, WPEditorFormatbarViewToolbarHeight + insets.bottom);; +} + +@end + @interface WPEditorViewController () @property (nonatomic, strong) NSString *htmlString; @@ -33,6 +70,8 @@ @interface WPEditorViewController () )coordinator { [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator]; - [self.toolbarView setNeedsLayout]; + [[self wrapperViewForInputView] setNeedsLayout]; } #pragma mark - Keyboard shortcuts @@ -272,8 +311,8 @@ - (void)buildTextViews self.editorView.autoresizesSubviews = YES; self.editorView.autoresizingMask = mask; self.editorView.backgroundColor = [UIColor whiteColor]; - self.editorView.sourceView.inputAccessoryView = self.toolbarView; - self.editorView.sourceViewTitleField.inputAccessoryView = self.toolbarView; + self.editorView.sourceView.inputAccessoryView = self.wrapperViewForInputView; + self.editorView.sourceViewTitleField.inputAccessoryView = self.wrapperViewForInputView; // Default placeholder text self.titlePlaceholderText = NSLocalizedString(@"Post title", @"Placeholder for the post title."); @@ -354,7 +393,9 @@ - (void)didTouchMediaOptions animated:YES completion:nil]; } - [self.delegate editorTrackStat:WPEditorStatTappedImage]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedImage]; + } } #pragma mark - Editor and Misc Methods @@ -518,7 +559,9 @@ - (void)showHTMLSource:(UIBarButtonItem *)barButtonItem setSelected:NO]; } - [self.delegate editorTrackStat:WPEditorStatTappedHTML]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedHTML]; + } } - (void)removeFormat @@ -550,21 +593,27 @@ - (void)setBold { [self.editorView setBold]; [self clearToolbar]; - [self.delegate editorTrackStat:WPEditorStatTappedBold]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedBold]; + } } - (void)setBlockQuote { [self.editorView setBlockQuote]; [self clearToolbar]; - [self.delegate editorTrackStat:WPEditorStatTappedBlockquote]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedBlockquote]; + } } - (void)setItalic { [self.editorView setItalic]; [self clearToolbar]; - [self.delegate editorTrackStat:WPEditorStatTappedItalic]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedItalic]; + } } - (void)setSubscript @@ -576,7 +625,9 @@ - (void)setUnderline { [self.editorView setUnderline]; [self clearToolbar]; - [self.delegate editorTrackStat:WPEditorStatTappedUnderline]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedUnderline]; + } } - (void)setSuperscript @@ -588,21 +639,27 @@ - (void)setStrikethrough { [self.editorView setStrikethrough]; [self clearToolbar]; - [self.delegate editorTrackStat:WPEditorStatTappedStrikethrough]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedStrikethrough]; + } } - (void)setUnorderedList { [self.editorView setUnorderedList]; [self clearToolbar]; - [self.delegate editorTrackStat:WPEditorStatTappedUnorderedList]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedUnorderedList]; + } } - (void)setOrderedList { [self.editorView setOrderedList]; [self clearToolbar]; - [self.delegate editorTrackStat:WPEditorStatTappedOrderedList]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedOrderedList]; + } } - (void)setHR @@ -698,7 +755,9 @@ - (void)linkBarButtonTapped } else { [self showInsertLinkDialogWithLink:self.editorView.selectedLinkURL title:[self.editorView selectedText]]; - [self.delegate editorTrackStat:WPEditorStatTappedLink]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedLink]; + } } } @@ -822,7 +881,9 @@ - (void)updateLink:(NSString *)url - (void)removeLink { [self.editorView removeLink]; - [self.delegate editorTrackStat:WPEditorStatTappedUnlink]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedUnlink]; + } } - (void)quickLink @@ -844,8 +905,6 @@ - (void)updateImage:(NSString *)url alt:(NSString *)alt /** * @brief Returns an URL from the general pasteboard. - * - * @param The URL or nil if no valid URL is found. */ - (NSURL*)urlFromPasteboard { @@ -923,6 +982,12 @@ - (void)editorTitleDidChange:(WPEditorView *)editorView } } +- (UIView *)wrapperViewForInputView { + if (_wrapperViewForInputView == nil) { + _wrapperViewForInputView = [[WrapperViewForInputView alloc] initWithToolbar:self.toolbarView]; + }; + return _wrapperViewForInputView; +} - (void)editorViewDidFinishLoadingDOM:(WPEditorView*)editorView { // DRM: the reason why we're doing is when the DOM finishes loading, instead of when the full @@ -944,7 +1009,7 @@ - (void)editorView:(WPEditorView*)editorView fieldCreated:(WPEditorField*)field { if (field == self.editorView.titleField) { - field.inputAccessoryView = self.toolbarView; + field.inputAccessoryView = self.wrapperViewForInputView; [field setRightToLeftTextEnabled:[self isCurrentLanguageDirectionRTL]]; [field setMultiline:NO]; @@ -953,7 +1018,7 @@ - (void)editorView:(WPEditorView*)editorView self.editorView.sourceViewTitleField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.titlePlaceholderText attributes:@{NSForegroundColorAttributeName: self.placeholderColor}]; } else if (field == self.editorView.contentField) { - field.inputAccessoryView = self.toolbarView; + field.inputAccessoryView = self.wrapperViewForInputView; [field setRightToLeftTextEnabled:[self isCurrentLanguageDirectionRTL]]; [field setMultiline:YES]; @@ -1000,7 +1065,7 @@ - (BOOL)editorView:(WPEditorView*)editorView [self showInsertLinkDialogWithLink:url.absoluteString title:title]; } else { - [[UIApplication sharedApplication] openURL:url]; + [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; } return YES; diff --git a/Classes/WPLegacyEditorFormatToolbar.m b/Classes/WPLegacyEditorFormatToolbar.m index 00df498..466796c 100644 --- a/Classes/WPLegacyEditorFormatToolbar.m +++ b/Classes/WPLegacyEditorFormatToolbar.m @@ -41,6 +41,16 @@ - (id)initWithCoder:(NSCoder *)coder { return self; } +- (void)layoutSubviews { + [super layoutSubviews]; + // HACK: Sergio Estevao (2017-10-10): Change the size of the items whe running on a device with a width smaller or equal than 320 (iPhone SE) + if (self.frame.size.width <= 320) { + for (UIBarButtonItem *item in self.items) { + item.width = roundf(item.image.size.width * 0.75); + } + } +} + - (void)setupToolbar { [self configureForHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; } @@ -92,11 +102,23 @@ - (void)configureForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass } } +- (UIBarButtonItem *)createButtonWithImageNamed:(NSString *)imageNamed tag:(WPLegacyEditorFormatAction)action +{ + UIImage *image = [self imageNamed:imageNamed]; + UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)]; + [button setImage:image forState:UIControlStateNormal]; + button.imageView.contentMode = UIViewContentModeScaleAspectFill; + [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside]; + button.tag = action; + UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:button]; + barButton.width = image.size.width; + barButton.image = image; + return barButton; +} + - (UIBarButtonItem *)mediaButton { if (_mediaButton == nil) { - UIImage *image = [self imageNamed:@"icon_format_media"]; - _mediaButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(buttonAction:)]; - _mediaButton.tag = WPLegacyEditorFormatActionMedia; + _mediaButton = [self createButtonWithImageNamed:@"icon_format_media" tag:WPLegacyEditorFormatActionMedia]; _mediaButton.accessibilityIdentifier = @"add media"; _mediaButton.accessibilityLabel = NSLocalizedString(@"add media", nil); } @@ -105,9 +127,7 @@ - (UIBarButtonItem *)mediaButton { - (UIBarButtonItem *)boldButton { if (_boldButton == nil) { - UIImage *image = [self imageNamed:@"icon_format_bold"]; - _boldButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(buttonAction:)]; - _boldButton.tag = WPLegacyEditorFormatActionBold; + _boldButton = [self createButtonWithImageNamed:@"icon_format_bold" tag:WPLegacyEditorFormatActionBold]; _boldButton.accessibilityIdentifier = @"strong"; _boldButton.accessibilityLabel = NSLocalizedString(@"bold", nil); } @@ -116,9 +136,7 @@ - (UIBarButtonItem *)boldButton { - (UIBarButtonItem *)italicsButton { if (_italicsButton == nil) { - UIImage *image = [self imageNamed:@"icon_format_italic"]; - _italicsButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(buttonAction:)]; - _italicsButton.tag = WPLegacyEditorFormatActionItalic; + _italicsButton = [self createButtonWithImageNamed:@"icon_format_italic" tag:WPLegacyEditorFormatActionItalic]; _italicsButton.accessibilityIdentifier = @"em"; _italicsButton.accessibilityLabel = NSLocalizedString(@"italic", nil); } @@ -127,9 +145,7 @@ - (UIBarButtonItem *)italicsButton { - (UIBarButtonItem *)underlineButton { if (_underlineButton == nil) { - UIImage *image = [self imageNamed:@"icon_format_underline"]; - _underlineButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(buttonAction:)]; - _underlineButton.tag = WPLegacyEditorFormatActionUnderline; + _underlineButton = [self createButtonWithImageNamed:@"icon_format_underline" tag:WPLegacyEditorFormatActionUnderline]; _underlineButton.accessibilityIdentifier = @"u"; _underlineButton.accessibilityLabel = NSLocalizedString(@"underline", nil); } @@ -138,9 +154,7 @@ - (UIBarButtonItem *)underlineButton { - (UIBarButtonItem *)delButton { if (_delButton == nil) { - UIImage *image = [self imageNamed:@"icon_format_strikethrough"]; - _delButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(buttonAction:)]; - _delButton.tag = WPLegacyEditorFormatActionDelete; + _delButton = [self createButtonWithImageNamed:@"icon_format_strikethrough" tag:WPLegacyEditorFormatActionDelete]; _delButton.accessibilityIdentifier = @"del"; _delButton.accessibilityLabel = NSLocalizedString(@"delete", nil); } @@ -149,9 +163,7 @@ - (UIBarButtonItem *)delButton { - (UIBarButtonItem *)linkButton { if (_linkButton == nil) { - UIImage *image = [self imageNamed:@"icon_format_link"]; - _linkButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(buttonAction:)]; - _linkButton.tag = WPLegacyEditorFormatActionLink; + _linkButton = [self createButtonWithImageNamed:@"icon_format_link" tag:WPLegacyEditorFormatActionLink]; _linkButton.accessibilityIdentifier = @"link"; _linkButton.accessibilityLabel = NSLocalizedString(@"link", nil); } @@ -160,9 +172,7 @@ - (UIBarButtonItem *)linkButton { - (UIBarButtonItem *)quoteButton { if (_quoteButton == nil) { - UIImage *image = [self imageNamed:@"icon_format_quote"]; - _quoteButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(buttonAction:)]; - _quoteButton.tag = WPLegacyEditorFormatActionQuote; + _quoteButton =[self createButtonWithImageNamed:@"icon_format_quote" tag:WPLegacyEditorFormatActionQuote]; _quoteButton.accessibilityIdentifier = @"blockquote"; _quoteButton.accessibilityLabel = NSLocalizedString(@"quote", nil); } @@ -171,9 +181,7 @@ - (UIBarButtonItem *)quoteButton { - (UIBarButtonItem *)moreButton { if (_moreButton == nil) { - UIImage *image = [self imageNamed:@"icon_format_more"]; - _moreButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(buttonAction:)]; - _moreButton.tag = WPLegacyEditorFormatActionMore; + _moreButton = [self createButtonWithImageNamed:@"icon_format_more" tag:WPLegacyEditorFormatActionMore]; _moreButton.accessibilityIdentifier = @"more"; _moreButton.accessibilityLabel = NSLocalizedString(@"more", nil); } @@ -195,7 +203,7 @@ - (void)disableAllButtons { } } -- (void)buttonAction:(UIBarButtonItem *)sender { +- (void)buttonAction:(UIButton *)sender { DDLogInfo(@"%@ %@", self, NSStringFromSelector(_cmd)); if (self.formatDelegate) { [self.formatDelegate formatToolbar:self actionPressed:sender.tag]; @@ -213,4 +221,4 @@ - (BOOL)enableInputClicksWhenVisible { return YES; } -@end \ No newline at end of file +@end diff --git a/Classes/WPLegacyEditorViewController.m b/Classes/WPLegacyEditorViewController.m index c08bc65..dccf39c 100644 --- a/Classes/WPLegacyEditorViewController.m +++ b/Classes/WPLegacyEditorViewController.m @@ -4,6 +4,49 @@ CGFloat const WPLegacyEPVCStandardOffset = 15.0; CGFloat const WPLegacyEPVCTextViewOffset = 10.0; +CGFloat const WPLegacyEPVCToolbarHeight = 44.0; + +@interface WPLegacyWrapperViewForInputView: UIView + @property (nonatomic, strong) WPLegacyEditorFormatToolbar *toolbar; +@end + +@implementation WPLegacyWrapperViewForInputView + +- (instancetype)initWithToolbar:(WPLegacyEditorFormatToolbar *)toolbar { + self = [super initWithFrame:CGRectMake(0, 0, self.frame.size.width, WPLegacyEPVCToolbarHeight)]; + if (self) { + _toolbar = toolbar; + self.autoresizingMask = UIViewAutoresizingFlexibleHeight; + self.backgroundColor = toolbar.backgroundColor ? toolbar.backgroundColor : [[WPLegacyEditorFormatToolbar appearance] backgroundColor]; + [self addSubview:toolbar]; + [[toolbar.topAnchor constraintEqualToAnchor:self.topAnchor] setActive:YES]; + [[toolbar.leftAnchor constraintEqualToAnchor:self.leftAnchor] setActive:YES]; + [[toolbar.rightAnchor constraintEqualToAnchor:self.rightAnchor] setActive:YES]; + toolbar.translatesAutoresizingMaskIntoConstraints = NO; + self.translatesAutoresizingMaskIntoConstraints = NO; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + self.toolbar.frame = CGRectMake(self.toolbar.frame.origin.x, 0, self.toolbar.frame.size.width, WPLegacyEPVCToolbarHeight); +} + +- (void)safeAreaInsetsDidChange { + [super safeAreaInsetsDidChange]; + [self invalidateIntrinsicContentSize]; +} + +- (CGSize)intrinsicContentSize { + UIEdgeInsets insets = UIEdgeInsetsZero; + if(@available(iOS 11, *)){ + insets = self.safeAreaInsets; + } + return CGSizeMake(UIViewNoIntrinsicMetric, WPLegacyEPVCToolbarHeight + insets.bottom); +} + +@end @interface WPLegacyEditorViewController () @@ -159,6 +202,11 @@ - (void)setupTextView self.textView.font = self.bodyFont; self.textView.textColor = self.bodyColor; self.textView.accessibilityLabel = NSLocalizedString(@"Content", @"Post content"); + + if (@available(iOS 11.0, *)) { + self.textView.smartQuotesType = UITextSmartQuotesTypeNo; + self.textView.smartDashesType = UITextSmartDashesTypeNo; + } } [self.view addSubview:self.textView]; @@ -167,7 +215,9 @@ - (void)setupTextView self.editorToolbar = [[WPLegacyEditorFormatToolbar alloc] init]; self.editorToolbar.formatDelegate = self; [self.editorToolbar sizeToFit]; - self.textView.inputAccessoryView = self.editorToolbar; + self.editorToolbar.translatesAutoresizingMaskIntoConstraints = false; + + self.textView.inputAccessoryView = [[WPLegacyWrapperViewForInputView alloc] initWithToolbar:self.editorToolbar]; } // Title TextField. @@ -183,8 +233,9 @@ - (void)setupTextView self.titleTextField.autoresizingMask = UIViewAutoresizingFlexibleWidth; self.titleTextField.accessibilityLabel = NSLocalizedString(@"Title", @"Post title"); self.titleTextField.returnKeyType = UIReturnKeyNext; + self.titleTextField.backgroundColor = self.textView.backgroundColor; } - [self.textView addSubview:self.titleTextField]; + [self.view addSubview:self.titleTextField]; // InputAccessoryView for title textField. if (!self.titleToolbar) { @@ -192,7 +243,8 @@ - (void)setupTextView [self.titleToolbar disableAllButtons]; self.titleToolbar.formatDelegate = self; [self.titleToolbar sizeToFit]; - self.titleTextField.inputAccessoryView = self.titleToolbar; + self.titleToolbar.translatesAutoresizingMaskIntoConstraints = false; + self.titleTextField.inputAccessoryView = [[WPLegacyWrapperViewForInputView alloc] initWithToolbar:self.titleToolbar]; } // One pixel separator bewteen title and content text fields. @@ -204,7 +256,7 @@ - (void)setupTextView self.separatorView.backgroundColor = self.separatorColor; self.separatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth; } - [self.textView addSubview:self.separatorView]; + [self.view addSubview:self.separatorView]; // Update the textView's textContainerInsets so text does not overlap content. CGFloat left = WPLegacyEPVCTextViewOffset; @@ -229,6 +281,29 @@ - (void)setupTextView [self.textView addSubview:self.tapToStartWritingLabel]; } +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + UIEdgeInsets insets = UIEdgeInsetsZero; + if (@available(iOS 11, *)) { + insets = self.view.safeAreaInsets; + } + CGFloat left = WPLegacyEPVCTextViewOffset + insets.left; + CGFloat right = WPLegacyEPVCTextViewOffset + insets.right; + CGFloat top = CGRectGetMaxY(self.separatorView.frame) + self.textView.font.lineHeight + insets.top; + CGFloat bottom = self.textView.font.lineHeight + insets.bottom; + self.textView.textContainerInset = UIEdgeInsetsMake(top, left, bottom, right); + + CGFloat width = CGRectGetWidth(self.view.frame) - (2 * WPLegacyEPVCStandardOffset) - (insets.left + insets.right); + CGRect titleFrame = CGRectMake(WPLegacyEPVCStandardOffset + insets.left, 0.0, width, self.titleFont.lineHeight * 2.0); + self.titleTextField.frame = titleFrame; + CGFloat y = CGRectGetMaxY(self.titleTextField.frame); + CGRect separatorFrame = CGRectMake(WPLegacyEPVCStandardOffset + insets.left, y, width, 1.0); + self.separatorView.frame = separatorFrame; + + CGRect tapToStartFrame = CGRectMake(WPLegacyEPVCStandardOffset + insets.left, self.textView.textContainerInset.top, width, self.textView.font.lineHeight); + self.tapToStartWritingLabel.frame = tapToStartFrame; +} + - (void)positionTextView:(NSNotification *)notification { NSDictionary *keyboardInfo = [notification userInfo]; @@ -443,28 +518,44 @@ - (void)formatToolbar:(WPLegacyEditorFormatToolbar *)formatToolbar actionPressed { switch (formatAction) { case WPLegacyEditorFormatActionBold: - [self.delegate editorTrackStat:WPEditorStatTappedBold]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedBold]; + } break; case WPLegacyEditorFormatActionItalic: - [self.delegate editorTrackStat:WPEditorStatTappedItalic]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedItalic]; + } break; case WPLegacyEditorFormatActionUnderline: - [self.delegate editorTrackStat:WPEditorStatTappedUnderline]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedUnderline]; + } break; case WPLegacyEditorFormatActionDelete: - [self.delegate editorTrackStat:WPEditorStatTappedStrikethrough]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedStrikethrough]; + } break; case WPLegacyEditorFormatActionLink: - [self.delegate editorTrackStat:WPEditorStatTappedLink]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedLink]; + } break; case WPLegacyEditorFormatActionQuote: - [self.delegate editorTrackStat:WPEditorStatTappedBlockquote]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedBlockquote]; + } break; case WPLegacyEditorFormatActionMore: - [self.delegate editorTrackStat:WPEditorStatTappedMore]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedMore]; + } break; case WPLegacyEditorFormatActionMedia: - [self.delegate editorTrackStat:WPEditorStatTappedImage]; + if ([self.delegate respondsToSelector: @selector(editorTrackStat:)]) { + [self.delegate editorTrackStat:WPEditorStatTappedImage]; + } break; } diff --git a/Example/EditorDemo.xcodeproj/project.pbxproj b/Example/EditorDemo.xcodeproj/project.pbxproj index 702dd43..3fbb6cb 100644 --- a/Example/EditorDemo.xcodeproj/project.pbxproj +++ b/Example/EditorDemo.xcodeproj/project.pbxproj @@ -269,12 +269,9 @@ isa = PBXProject; attributes = { CLASSPREFIX = WP; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Automattic, Inc."; TargetAttributes = { - 748D2A84193E516000D5ACC8 = { - DevelopmentTeam = PZYM8XX95Q; - }; 748D2AA8193E516000D5ACC8 = { TestTargetID = 748D2A84193E516000D5ACC8; }; @@ -345,13 +342,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-EditorDemoTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 4695D4EE8336F768836ED41D /* [CP] Embed Pods Frameworks */ = { @@ -360,9 +360,16 @@ files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-EditorDemo/Pods-EditorDemo-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework", + "${BUILT_PRODUCTS_DIR}/NSObject-SafeExpectations/NSObject_SafeExpectations.framework", + "${BUILT_PRODUCTS_DIR}/WordPress-iOS-Editor/WordPressEditor.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NSObject_SafeExpectations.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WordPressEditor.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -375,9 +382,12 @@ files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-EditorDemoTests/Pods-EditorDemoTests-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -390,13 +400,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-EditorDemo-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; D3F5DB2B0020A9B77E64179A /* [CP] Copy Pods Resources */ = { @@ -492,19 +505,30 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -517,7 +541,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -532,25 +556,36 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -563,6 +598,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "EditorDemo/EditorDemo-Prefix.pch"; @@ -579,6 +615,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "EditorDemo/EditorDemo-Prefix.pch"; @@ -595,7 +632,6 @@ buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/EditorDemo.app/EditorDemo"; FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); @@ -619,7 +655,6 @@ buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/EditorDemo.app/EditorDemo"; FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); diff --git a/Example/EditorDemo.xcodeproj/xcshareddata/xcschemes/EditorDemo.xcscheme b/Example/EditorDemo.xcodeproj/xcshareddata/xcschemes/EditorDemo.xcscheme index 9e0052a..ebf6bc2 100644 --- a/Example/EditorDemo.xcodeproj/xcshareddata/xcschemes/EditorDemo.xcscheme +++ b/Example/EditorDemo.xcodeproj/xcshareddata/xcschemes/EditorDemo.xcscheme @@ -1,6 +1,6 @@ NSPhotoLibraryUsageDescription To add photos or videos to your posts. + NSMicrophoneUsageDescription + To take photos or videos to use in your posts. NSCameraUsageDescription To take photos or videos to use in your posts. diff --git a/Example/EditorDemo/WPViewController.m b/Example/EditorDemo/WPViewController.m index 728db80..266d0fa 100644 --- a/Example/EditorDemo/WPViewController.m +++ b/Example/EditorDemo/WPViewController.m @@ -33,25 +33,13 @@ - (void)viewDidLoad - (void)customizeAppearance { [super customizeAppearance]; - // Note 12-June-2017 - Commented out all of the code originally referencing the WordPressShared pod which no longer exists. - - // WORKAROUND: Preload the Noto regular font to ensure it is not overridden - // by any of the Noto varients. Size is arbitrary. - // See: https://github.com/wordpress-mobile/WordPress-Shared-iOS/issues/79 - // Remove this when #79 is resolved. -// [WPFontManager notoRegularFontOfSize:16.0]; -// [WPFontManager loadNotoFontFamily]; - -// self.placeholderColor = [WPStyleGuide grey]; -// self.editorView.sourceViewTitleField.font = [WPFontManager notoBoldFontOfSize:24.0]; -// self.editorView.sourceContentDividerView.backgroundColor = [WPStyleGuide greyLighten30]; -// [self.toolbarView setBorderColor:[WPStyleGuide greyLighten10]]; -// [self.toolbarView setItemTintColor: [WPStyleGuide greyLighten10]]; -// [self.toolbarView setSelectedItemTintColor: [WPStyleGuide baseDarkerBlue]]; + [self.toolbarView setBorderColor:[UIColor lightGrayColor]]; + [self.toolbarView setItemTintColor: [UIColor lightGrayColor]]; + [self.toolbarView setSelectedItemTintColor: [UIColor darkGrayColor]]; [self.toolbarView setDisabledItemTintColor:[UIColor colorWithRed:0.78 green:0.84 blue:0.88 alpha:0.5]]; // Explicit design decision to use non-standard colors. See: // https://github.com/wordpress-mobile/WordPress-Editor-iOS/issues/657#issuecomment-113651034 - [self.toolbarView setBackgroundColor: [UIColor colorWithRed:0xF9/255.0 green:0xFB/255.0 blue:0xFC/255.0 alpha:1]]; + [self.toolbarView setBackgroundColor: [UIColor colorWithRed:0xF9/255.0 green:0xFB/255.0 blue:0xFC/255.0 alpha:1]]; } #pragma mark - Navigation Bar @@ -118,6 +106,10 @@ - (void)editorViewController:(WPEditorViewController *)editorViewController fiel DDLogInfo(@"Editor field created: %@", field.nodeId); } +- (void)editorTrackStat:(WPEditorStat)stat { + DDLogInfo(@"Editor stat tracked: %lu", (unsigned long)stat); +} + - (void)editorViewController:(WPEditorViewController*)editorViewController imageTapped:(NSString *)imageId url:(NSURL *)url diff --git a/Example/Podfile b/Example/Podfile index d1d046e..47952bf 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,14 +1,14 @@ -platform :ios, '9.0' +platform :ios, '10.0' use_frameworks! # Don't inhibit all warnings for all pods… do it individually. We need the editor # POD to show all warnings. target 'EditorDemo' do pod 'WordPress-iOS-Editor', :path => '../' - pod 'CocoaLumberjack', '~> 3.2.0', :inhibit_warnings => true + pod 'CocoaLumberjack', '~> 3.2.1', :inhibit_warnings => true end target 'EditorDemoTests' do - pod 'CocoaLumberjack', '~> 3.2.0', :inhibit_warnings => true + pod 'CocoaLumberjack', '~> 3.2.1', :inhibit_warnings => true end diff --git a/Example/Podfile.lock b/Example/Podfile.lock index f297821..33de337 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,28 +1,28 @@ PODS: - - CocoaLumberjack (3.2.0): - - CocoaLumberjack/Default (= 3.2.0) - - CocoaLumberjack/Extensions (= 3.2.0) - - CocoaLumberjack/Default (3.2.0) - - CocoaLumberjack/Extensions (3.2.0): + - CocoaLumberjack (3.2.1): + - CocoaLumberjack/Default (= 3.2.1) + - CocoaLumberjack/Extensions (= 3.2.1) + - CocoaLumberjack/Default (3.2.1) + - CocoaLumberjack/Extensions (3.2.1): - CocoaLumberjack/Default - NSObject-SafeExpectations (0.0.2) - - WordPress-iOS-Editor (1.9.3): + - WordPress-iOS-Editor (1.9.7): - CocoaLumberjack (~> 3.2.0) - NSObject-SafeExpectations (~> 0.0.2) DEPENDENCIES: - - CocoaLumberjack (~> 3.2.0) + - CocoaLumberjack (~> 3.2.1) - WordPress-iOS-Editor (from `../`) EXTERNAL SOURCES: WordPress-iOS-Editor: - :path: "../" + :path: ../ SPEC CHECKSUMS: - CocoaLumberjack: 9b4aed7073d242f29cc2f62068d995faf67f703a + CocoaLumberjack: 2800c03334042fe80589423c8d80e582dcaec482 NSObject-SafeExpectations: 7d7f48df90df4e11da7cfe86b64f45eff7a7f521 - WordPress-iOS-Editor: ed02135d783ecb9aa4ee5e2462935432d464d461 + WordPress-iOS-Editor: 03b3bc631a31520ccf78e665548286c6d12c17f4 -PODFILE CHECKSUM: cb6a541ba5f4aad4728b3cc32bb1c0621d6f7bfa +PODFILE CHECKSUM: 22652f63d69fb0891ea4dd0ef26f5e00650a21cb -COCOAPODS: 1.2.1 +COCOAPODS: 1.3.1 diff --git a/README.md b/README.md index 7964b03..375cb24 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ +🚨 Deprecation Notice: 🚨 As of December 2017 this project has been deprecated and will no longer be updated. The code is here for historical purposes only. + +

+Aztec's Logo' +

+ +We encourage you to try [Aztec](https://github.com/wordpress-mobile/AztecEditor-iOS), +our new, open-source fully native HTML editor. + +If you find Aztec is missing some functionality you were relying on from this editor, please file an issue [in the Aztec repo](https://github.com/wordpress-mobile/AztecEditor-iOS/issues). + +____ + + [![Build Status](https://travis-ci.org/wordpress-mobile/WordPress-Editor-iOS.svg?branch=develop)](https://travis-ci.org/wordpress-mobile/WordPress-Editor-iOS) ![WordPress Logo](http://s.w.org/about/images/logos/wordpress-logo-hoz-rgb.png) @@ -14,7 +28,7 @@ The WordPress-Editor-iOS is the text editor used in the [WordPress iOS app](http You can install the editor in your app via [CocoaPods](http://cocoapods.org): ```ruby -platform :ios, '9.0' +platform :ios, '10.0' pod 'WordPress-iOS-Editor' ``` @@ -26,7 +40,7 @@ pod try WordPress-iOS-Editor ## Requirements -WordPress-iOS-Editor requires iOS 9.0 or higher. It depends on the following Apple frameworks: +WordPress-iOS-Editor requires iOS 10.0 or higher. It depends on the following Apple frameworks: * Foundation.framework * UIKit.framework diff --git a/WordPress-iOS-Editor.podspec b/WordPress-iOS-Editor.podspec index 57c356a..18b9092 100644 --- a/WordPress-iOS-Editor.podspec +++ b/WordPress-iOS-Editor.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPress-iOS-Editor" - s.version = "1.9.3" + s.version = "1.9.7" s.summary = "Reusable component rich text editor for WordPress.com in an iOS application." s.description = <<-DESC @@ -12,7 +12,7 @@ Pod::Spec.new do |s| s.author = { "Automattic" => "mobile@automattic.com", "Matt Bumgardner" => "matt.bumgardner@automattic.com", "Diego Rey Mendez" => "diego.rey.mendez@automattic.com", "Sergio Estevao" => "sergio@automattic.com" } s.source = { :git => "https://github.com/wordpress-mobile/WordPress-iOS-Editor.git", :tag => s.version.to_s } s.social_media_url = 'http://twitter.com/WordPressiOS' - s.platform = :ios, '9.0' + s.platform = :ios, '10.0' s.source_files = 'Classes' s.resources = ["Assets/*.png", "Assets/*.html", "Assets/*.js", "Assets/*.svg", "Assets/*.css", "Assets/*.storyboard", "Assets/*.xib"] s.prefix_header_file = "Classes/WordPress-iOS-Editor-Prefix.pch"