Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* [*] Fix layout issues in Privacy Settings section of App Settings [#23936]
* [*] Fix incorrect chevron icons direction in RTL languages [#23940]
* [*] Fix an issue with clear navigation bar background in revision browser [#23941]
* [*] Fix an issue with comments being lost on request failure [#23942]

25.6
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1068,13 +1068,15 @@ private extension CommentDetailViewController {
return
}

replyTextView?.setShowingLoadingIndicator(true)

commentService.createReply(for: comment, content: content) { reply in
self.commentService.uploadComment(reply, success: { [weak self] in
self?.displayReplyNotice(success: true)
self?.didSendReply(success: true)
self?.refreshCommentReplyIfNeeded()
}, failure: { [weak self] error in
DDLogError("Failed uploading comment reply: \(String(describing: error))")
self?.displayReplyNotice(success: false)
self?.didSendReply(success: false, error: error)
})
}
}
Expand All @@ -1084,21 +1086,30 @@ private extension CommentDetailViewController {
return
}

replyTextView?.setShowingLoadingIndicator(true)

commentService.replyToHierarchicalComment(withID: NSNumber(value: comment.commentID),
post: post,
content: content,
success: { [weak self] in
self?.displayReplyNotice(success: true)
self?.didSendReply(success: true)
self?.refreshCommentReplyIfNeeded()
}, failure: { [weak self] error in
DDLogError("Failed creating post comment reply: \(String(describing: error))")
self?.displayReplyNotice(success: false)
self?.didSendReply(success: false, error: error)
})
}

func displayReplyNotice(success: Bool) {
func didSendReply(success: Bool, error: Error? = nil) {
replyTextView?.setShowingLoadingIndicator(false)
if success {
replyTextView?.text = ""
} else {
replyTextView?.becomeFirstResponder()
}

let message = success ? ReplyMessages.successMessage : ReplyMessages.failureMessage
displayNotice(title: message)
displayNotice(title: message, message: error?.localizedDescription)
}

func configureSuggestionsView() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,12 +417,15 @@ extension NotificationDetailsViewController {
replyTextView.accessibilityIdentifier = .replyTextViewAccessibilityId
replyTextView.accessibilityLabel = NSLocalizedString("Reply Text", comment: "Notifications Reply Accessibility Identifier")
replyTextView.delegate = self
replyTextView.onReply = { [weak self] content in
let group = self?.note.contentGroup(ofKind: .comment)
replyTextView.onReply = { [weak self, weak replyTextView] content in
guard let self, let replyTextView else {
return
}
let group = self.note.contentGroup(ofKind: .comment)
guard let block: FormattableCommentContent = group?.blockOfKind(.comment) else {
return
}
self?.replyCommentWithBlock(block, content: content)
self.replyCommentWithBlock(block, content: content, textView: replyTextView)
}

replyTextView.setContentCompressionResistancePriority(.required, for: .vertical)
Expand Down Expand Up @@ -1085,26 +1088,30 @@ private extension NotificationDetailsViewController {
_ = navigationController?.popToRootViewController(animated: true)
}

func replyCommentWithBlock(_ block: FormattableCommentContent, content: String) {
func replyCommentWithBlock(_ block: FormattableCommentContent, content: String, textView: ReplyTextView) {
guard let replyAction = block.action(id: ReplyToCommentAction.actionIdentifier()) else {
return
}

let generator = UINotificationFeedbackGenerator()
generator.prepare()
generator.notificationOccurred(.success)

let actionContext = ActionContext(block: block, content: content) { [weak self] (request, success) in
textView.setShowingLoadingIndicator(false)
if success {
generator.notificationOccurred(.success)
WPAppAnalytics.track(.notificationsCommentRepliedTo)
textView.text = ""
let message = NSLocalizedString("Reply Sent!", comment: "The app successfully sent a comment")
self?.displayNotice(title: message)
} else {
generator.notificationOccurred(.error)
textView.becomeFirstResponder()
self?.displayReplyError(with: block, content: content)
}
}

textView.setShowingLoadingIndicator(true)
replyAction.execute(context: actionContext)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,30 +143,14 @@ import Gridicons

// MARK: - IBActions
@IBAction fileprivate func btnReplyPressed() {
guard let handler = onReply else {
return
}

// We can't reply without an internet connection
let appDelegate = WordPressAppDelegate.shared
guard appDelegate!.connectionAvailable else {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a poor practice to check connectivity and not send the request.

let title = NSLocalizedString("No Connection", comment: "Title of error prompt when no internet connection is available.")
let message = NSLocalizedString("The Internet connection appears to be offline.",
comment: "Message of error prompt shown when a user tries to perform an action without an internet connection.")
WPError.showAlert(withTitle: title, message: message)
textView.resignFirstResponder()
return
}
guard let onReply else { return }

// Load the new text
let newText = textView.text
textView.resignFirstResponder()

// Cleanup + Shrink
text = String()

// Hit the handler
handler(newText!)
onReply(newText ?? "")
}

@IBAction fileprivate func btnEnterFullscreenPressed(_ sender: Any) {
Expand Down Expand Up @@ -286,8 +270,12 @@ import Gridicons
comment: "Accessibility Label for the enter full screen button on the comment reply text view")

// Reply button
replyButton.setTitleColor(UIAppColor.brand, for: .normal)
replyButton.titleLabel?.text = NSLocalizedString("Reply", comment: "Reply to a comment.")
replyButton.configuration = {
var configuration = UIButton.Configuration.plain()
configuration.baseForegroundColor = UIAppColor.brand
configuration.title = NSLocalizedString("Reply", comment: "Reply to a comment.")
return configuration
}()
replyButton.accessibilityIdentifier = "reply-button"
replyButton.accessibilityLabel = NSLocalizedString("Reply", comment: "Accessibility label for the reply button")
refreshReplyButton()
Expand All @@ -308,6 +296,16 @@ import Gridicons
frame.size.height = minimumHeight
}

@objc func setShowingLoadingIndicator(_ isLoading: Bool) {
isUserInteractionEnabled = !isLoading

textView.alpha = isLoading ? 0.33 : 1.0

replyButton.isEnabled = !isLoading
replyButton.configuration?.title = isLoading ? nil : NSLocalizedString("Reply", comment: "Reply to a comment.")
replyButton.configuration?.showsActivityIndicator = isLoading
}

// MARK: - Refresh Helpers
fileprivate func refreshInterface() {
refreshPlaceholder()
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="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
Expand Down Expand Up @@ -102,7 +102,6 @@
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Reply"/>
<connections>
<action selector="btnReplyPressed" destination="-1" eventType="touchUpInside" id="Jeq-hG-haN"/>
</connections>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,9 @@ - (void)sendReplyWithNewContent:(NSString *)content
NSString *successMessage = NSLocalizedString(@"Reply Sent!", @"The app successfully sent a comment");
[weakSelf displayNoticeWithTitle:successMessage message:nil];

[weakSelf.replyTextView setShowingLoadingIndicator:NO];
weakSelf.replyTextView.text = @"";

[weakSelf trackReplyTo:replyToComment];
[weakSelf.tableView deselectSelectedRowWithAnimation:YES];
[weakSelf refreshReplyTextViewPlaceholder];
Expand All @@ -931,11 +934,16 @@ - (void)sendReplyWithNewContent:(NSString *)content
DDLogError(@"Error sending reply: %@", error);
[generator notificationOccurred:UINotificationFeedbackTypeError];
NSString *message = NSLocalizedString(@"There has been an unexpected error while sending your reply", "Reply Failure Message");
[weakSelf displayNoticeWithTitle:message message:nil];
[weakSelf.replyTextView setShowingLoadingIndicator:NO];
[weakSelf displayNoticeWithTitle:message message:[error localizedDescription]];

[weakSelf.replyTextView becomeFirstResponder];

[weakSelf refreshTableViewAndNoResultsView:NO];
};

[self.replyTextView setShowingLoadingIndicator:YES];

CommentService *service = [[CommentService alloc] initWithCoreDataStack:[ContextManager sharedInstance]];

if (replyToComment) {
Expand Down