Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add banner to subscription action #4312

Merged
merged 18 commits into from Sep 9, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions Wikipedia/Code/TalkPageDataController.swift
Expand Up @@ -65,6 +65,17 @@ class TalkPageDataController {
talkPageFetcher.subscribeToTopic(talkPageTitle: pageTitle, siteURL: siteURL, topic: topicName, shouldSubscribe: shouldSubscribe, completion: completion)
}

func fetchSubscriptions(for topics: [String], completion: @escaping (Result<[String], Error>) -> Void) {
talkPageFetcher.getSubscribedTopics(siteURL: siteURL, topics: topics) { result in
switch result {
case let .success(result):
completion(.success(result))
case let .failure(error):
completion(.failure(error))
}
}
}

// MARK: Private

private func fetchTalkPageItems(dispatchGroup group: DispatchGroup, completion: @escaping ([TalkPageItem], [Error]) -> Void) {
Expand Down
123 changes: 72 additions & 51 deletions Wikipedia/Code/TalkPageViewController.swift
@@ -1,5 +1,6 @@
import UIKit
import WMF
import CocoaLumberjackSwift

class TalkPageViewController: ViewController {

Expand All @@ -23,63 +24,63 @@ class TalkPageViewController: ViewController {
// MARK: - Overflow menu properties

fileprivate var userTalkOverflowSubmenuActions: [UIAction] {
let contributionsAction = UIAction(title: MenuLocalizedStrings.contributions, image: UIImage(named: "user-contributions"), handler: { _ in
let contributionsAction = UIAction(title: TalkPageLocalizedStrings.contributions, image: UIImage(named: "user-contributions"), handler: { _ in
})

let userGroupsAction = UIAction(title: MenuLocalizedStrings.userGroups, image: UIImage(systemName: "person.2"), handler: { _ in
let userGroupsAction = UIAction(title: TalkPageLocalizedStrings.userGroups, image: UIImage(systemName: "person.2"), handler: { _ in
})

let logsAction = UIAction(title: MenuLocalizedStrings.logs, image: UIImage(systemName: "list.bullet"), handler: { _ in
let logsAction = UIAction(title: TalkPageLocalizedStrings.logs, image: UIImage(systemName: "list.bullet"), handler: { _ in
})

return [contributionsAction, userGroupsAction, logsAction]
}

fileprivate var overflowSubmenuActions: [UIAction] {
let goToArchivesAction = UIAction(title: MenuLocalizedStrings.archives, image: UIImage(systemName: "archivebox"), handler: { _ in

let goToArchivesAction = UIAction(title: TalkPageLocalizedStrings.archives, image: UIImage(systemName: "archivebox"), handler: { _ in
})
let pageInfoAction = UIAction(title: MenuLocalizedStrings.pageInfo, image: UIImage(systemName: "info.circle"), handler: { _ in

let pageInfoAction = UIAction(title: TalkPageLocalizedStrings.pageInfo, image: UIImage(systemName: "info.circle"), handler: { _ in
})
let goToPermalinkAction = UIAction(title: MenuLocalizedStrings.permaLink, image: UIImage(systemName: "link"), handler: { _ in

let goToPermalinkAction = UIAction(title: TalkPageLocalizedStrings.permaLink, image: UIImage(systemName: "link"), handler: { _ in
})
let relatedLinksAction = UIAction(title: MenuLocalizedStrings.relatedLinks, image: UIImage(systemName: "arrowshape.turn.up.forward"), handler: { _ in

let relatedLinksAction = UIAction(title: TalkPageLocalizedStrings.relatedLinks, image: UIImage(systemName: "arrowshape.turn.up.forward"), handler: { _ in
})

var actions = [goToArchivesAction, pageInfoAction, goToPermalinkAction, relatedLinksAction]

if viewModel.pageType == .user {
let aboutTalkUserPagesAction = UIAction(title: MenuLocalizedStrings.aboutUserTalk, image: UIImage(systemName: "doc.plaintext"), handler: { _ in
let aboutTalkUserPagesAction = UIAction(title: TalkPageLocalizedStrings.aboutUserTalk, image: UIImage(systemName: "doc.plaintext"), handler: { _ in

})
actions.insert(contentsOf: userTalkOverflowSubmenuActions, at: 1)
actions.append(aboutTalkUserPagesAction)
} else {
let changeLanguageAction = UIAction(title: MenuLocalizedStrings.changeLanguage, image: UIImage(named: "language-talk-page"), handler: { _ in
let changeLanguageAction = UIAction(title: TalkPageLocalizedStrings.changeLanguage, image: UIImage(named: "language-talk-page"), handler: { _ in
})
let aboutTalkPagesAction = UIAction(title: MenuLocalizedStrings.aboutArticleTalk, image: UIImage(systemName: "doc.plaintext"), handler: { _ in
let aboutTalkPagesAction = UIAction(title: TalkPageLocalizedStrings.aboutArticleTalk, image: UIImage(systemName: "doc.plaintext"), handler: { _ in

})
actions.insert(changeLanguageAction, at: 3)
actions.append(aboutTalkPagesAction)
}
return actions
}

var overflowMenu: UIMenu {

let openAllAction = UIAction(title: MenuLocalizedStrings.openAllThreads, image: UIImage(systemName: "square.stack"), handler: { _ in
let openAllAction = UIAction(title: TalkPageLocalizedStrings.openAllThreads, image: UIImage(systemName: "square.stack"), handler: { _ in

})

let revisionHistoryAction = UIAction(title: CommonStrings.revisionHistory, image: UIImage(systemName: "clock.arrow.circlepath"), handler: { _ in

})

let openInWebAction = UIAction(title: MenuLocalizedStrings.readInWeb, image: UIImage(systemName: "display"), handler: { _ in
let openInWebAction = UIAction(title: TalkPageLocalizedStrings.readInWeb, image: UIImage(systemName: "display"), handler: { _ in

})

Expand All @@ -97,21 +98,21 @@ class TalkPageViewController: ViewController {

viewModel.delegate = self
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func loadView() {
let talkPageView = TalkPageView(frame: UIScreen.main.bounds)
view = talkPageView
scrollView = talkPageView.collectionView
}

override func viewDidLoad() {
super.viewDidLoad()

navigationItem.title = WMFLocalizedString("talk-pages-view-title", value: "Talk", comment: "Title of user and article talk pages view.")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for cleaning these up!

navigationItem.title = TalkPageLocalizedStrings.title

// Not adding fallback for other versions since we're dropping iOS 13 on the next release
// TODO: this version check should be removed
Expand All @@ -120,10 +121,10 @@ class TalkPageViewController: ViewController {
navigationItem.rightBarButtonItem = rightBarButtonItem
rightBarButtonItem.tintColor = theme.colors.link
}

talkPageView.collectionView.dataSource = self
talkPageView.collectionView.delegate = self

// Needed for reply compose views to display on top of navigation bar.
navigationController?.setNavigationBarHidden(true, animated: false)
navigationMode = .forceBar
Expand All @@ -136,27 +137,26 @@ class TalkPageViewController: ViewController {
private func setupHeaderView() {
let headerView = TalkPageHeaderView()
self.headerView = headerView

headerView.configure(viewModel: viewModel)
navigationBar.isBarHidingEnabled = false
navigationBar.isUnderBarViewHidingEnabled = true
navigationBar.allowsUnderbarHitsFallThrough = true

navigationBar.addUnderNavigationBarView(headerView, shouldIgnoreSafeArea: true)
useNavigationBarVisibleHeightForScrollViewInsets = false
updateScrollViewInsets()

headerView.apply(theme: theme)
}

// MARK: - Public


// MARK: - Themeable

override func apply(theme: Theme) {
super.apply(theme: theme)

viewModel.theme = theme
headerView?.apply(theme: theme)
talkPageView.apply(theme: theme)
Expand Down Expand Up @@ -206,7 +206,7 @@ class TalkPageViewController: ViewController {
talkPageURLComponents?.path = "/wiki/\(viewModel.pageTitle)"
return talkPageURLComponents?.url
}

@objc fileprivate func userDidTapShareButton() {
guard let talkPageURL = talkPageURL else {
return
Expand Down Expand Up @@ -234,32 +234,44 @@ class TalkPageViewController: ViewController {

toolbar.items = [shareButton, .flexibleSpaceToolbar(), revisionButton, .flexibleSpaceToolbar(), findButton,.flexibleSpaceToolbar(), addTopicButton]

shareButton.accessibilityLabel = WMFLocalizedString("talk-page-share-button", value: "Share talk page", comment: "Title for share talk page button")
findButton.accessibilityLabel = WMFLocalizedString("talk-page-find-in-page-button", value: "Find in page", comment: "Title for find content in page button")
shareButton.accessibilityLabel = TalkPageLocalizedStrings.shareButtonAccesibilityLabel
findButton.accessibilityLabel = TalkPageLocalizedStrings.findButtonAccesibilityLabel
revisionButton.accessibilityLabel = CommonStrings.revisionHistory
addTopicButton.accessibilityLabel = WMFLocalizedString("talk-page-add-topic-button", value: "Add topic", comment: "Title for add topic to talk page button")
addTopicButton.accessibilityLabel = TalkPageLocalizedStrings.addTopicButtonAccesibilityLabel
}


fileprivate func handleSubscriptionAlert(isSubscribedToTopic: Bool) {
let title = isSubscribedToTopic ? TalkPageLocalizedStrings.subscribedAlertTitle : TalkPageLocalizedStrings.unsubscribedAlertTitle
let subtitle = isSubscribedToTopic ? TalkPageLocalizedStrings.subscribedAlertSubtitle : TalkPageLocalizedStrings.unsubscribedAlertSubtitle
let image = isSubscribedToTopic ? UIImage(systemName: "bell.fill") : UIImage(systemName: "bell.slash.fill")

if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: title)
} else {
WMFAlertManager.sharedInstance.showBottomAlertWithMessage(title, subtitle: subtitle, image: image ?? UIImage(), dismissPreviousAlerts: true)
}
}

}

// MARK: - UICollectionViewDelegate, UICollectionViewDataSource

extension TalkPageViewController: UICollectionViewDelegate, UICollectionViewDataSource {

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.topics.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TalkPageCell.reuseIdentifier, for: indexPath) as? TalkPageCell else {
return UICollectionViewCell()
return UICollectionViewCell()
}

let viewModel = viewModel.topics[indexPath.row]

cell.delegate = self
cell.replyDelegate = self

cell.configure(viewModel: viewModel)
cell.apply(theme: theme)

Expand All @@ -270,38 +282,37 @@ extension TalkPageViewController: UICollectionViewDelegate, UICollectionViewData
guard let cell = collectionView.cellForItem(at: indexPath) as? TalkPageCell else {
return
}

userDidTapDisclosureButton(cellViewModel: cell.viewModel, cell: cell)
}

}

// MARK: - TalkPageCellDelegate

// TODO
extension TalkPageViewController: TalkPageCellDelegate {

func userDidTapDisclosureButton(cellViewModel: TalkPageCellViewModel?, cell: TalkPageCell) {
guard let cellViewModel = cellViewModel, let indexOfConfiguredCell = viewModel.topics.firstIndex(where: {$0 === cellViewModel}) else {
return
}

let configuredCellViewModel = viewModel.topics[indexOfConfiguredCell]
configuredCellViewModel.isThreadExpanded.toggle()

cell.configure(viewModel: configuredCellViewModel)
talkPageView.collectionView.collectionViewLayout.invalidateLayout()
}

func userDidTapSubscribeButton(cellViewModel: TalkPageCellViewModel?, cell: TalkPageCell) {
guard let cellViewModel = cellViewModel, let indexOfConfiguredCell = viewModel.topics.firstIndex(where: {$0 === cellViewModel}) else {
return
}

let configuredCellViewModel = viewModel.topics[indexOfConfiguredCell]
configuredCellViewModel.isSubscribed.toggle()

cell.configure(viewModel: configuredCellViewModel)
self.handleSubscriptionAlert(isSubscribedToTopic: configuredCellViewModel.isSubscribed)
}
}

Expand Down Expand Up @@ -329,9 +340,10 @@ extension TalkPageViewController: TalkPageReplyComposeDelegate {
}

extension TalkPageViewController {
enum MenuLocalizedStrings {
enum TalkPageLocalizedStrings {
static let title = WMFLocalizedString("talk-pages-view-title", value: "Talk", comment: "Title of user and article talk pages view.")
static let openAllThreads = WMFLocalizedString("talk-page-menu-open-all", value: "Open all threads", comment: "Title for menu option open all talk page threads")
static let readInWeb = WMFLocalizedString("talk-page-open-in-web", value: "Read in web", comment: "Title for menu option to open a talk page in a web browser")
static let readInWeb = WMFLocalizedString("talk-page-read-in-web", value: "Read in web", comment: "Title for menu option to read a talk page in a web browser")
static let archives = WMFLocalizedString("talk-page-archives", value: "Archives", comment: "Title for menu option that redirects to talk page archives")
static let pageInfo = WMFLocalizedString("talk-page-page-info", value: "Page information", comment: "Title for menu option to go to the talk page information link")
static let permaLink = WMFLocalizedString("talk-page-permanent-link", value: "Permanent link", comment: "Title for menu option to open the talk page's permanent link in a web browser")
Expand All @@ -342,5 +354,14 @@ extension TalkPageViewController {
static let contributions = WMFLocalizedString("talk-page-user-contributions", value: "Contributions", comment: "Title for menu option for information on the user's contributions")
static let userGroups = WMFLocalizedString("talk-pages-user-groups", value: "User groups", comment: "Title for menu option for information on the user's user groups")
static let logs = WMFLocalizedString("talk-pages-user-logs", value: "Logs", comment: "Title for menu option to consult the user's public logs")

static let subscribedAlertTitle = WMFLocalizedString("talk-page-subscribed-alert-title", value: "You have subscribed!", comment: "Title for alert informing that the user subscribed to a topic")
static let unsubscribedAlertTitle = WMFLocalizedString("talk-page-unsubscribed-alert-title", value: "You have unsubscribed.", comment: "Title for alert informing that the user unsubscribed to a topic")
static let subscribedAlertSubtitle = WMFLocalizedString("talk-page-subscribed-alert-subtitle", value: "You will receive notifications about new comments in this topic.", comment: "Subtitle for alert informing that the user will receive notifications for a subscribed topic")
static let unsubscribedAlertSubtitle = WMFLocalizedString("talk-page-unsubscribed-alert-subtitle", value: "You will no longer receive notifications about new comments in this topic.", comment: "Subtitle for alert informing that the user will no longer receive notifications for a topic")

static let shareButtonAccesibilityLabel = WMFLocalizedString("talk-page-share-button", value: "Share talk page", comment: "Title for share talk page button")
static let findButtonAccesibilityLabel = WMFLocalizedString("talk-page-find-in-page-button", value: "Find in page", comment: "Title for find content in page button")
static let addTopicButtonAccesibilityLabel = WMFLocalizedString("talk-page-add-topic-button", value: "Add topic", comment: "Title for add topic to talk page button")
}
}
13 changes: 13 additions & 0 deletions Wikipedia/Code/TalkPageViewModel.swift
Expand Up @@ -76,6 +76,19 @@ final class TalkPageViewModel {
}
}

func updateSubscriptionToTopic(topic: String, shouldSubscribe: Bool, completion: @escaping (Result<Bool, Error>) -> Void) {
dataController.subscribeToTopic(topicName: topic, shouldSubscribe: shouldSubscribe) { [self] result in
switch result {
case let .success(result) :
let topicUpdated = topics.filter { $0.topicTitle == topic}
topicUpdated[0].isSubscribed = result
completion(.success(result))
case let .failure(error):
completion(.failure(error))
}
}
}

// MARK: - Private

private func populateHeaderData(articleSummary: WMFArticle?, items: [TalkPageItem]) {
Expand Down
6 changes: 6 additions & 0 deletions Wikipedia/Code/WMFAlertManager.swift
Expand Up @@ -79,6 +79,12 @@ open class WMFAlertManager: NSObject, RMessageProtocol, Themeable {
RMessage.showNotification(in: nil, title: message, subtitle: nil, iconImage: nil, type: .error, customTypeName: nil, duration: sticky ? -1 : 2, callback: tapCallBack, buttonTitle: nil, buttonCallback: nil, at: .top, canBeDismissedByUser: true)
})
}

@objc func showBottomAlertWithMessage(_ message: String, subtitle: String, image: UIImage, dismissPreviousAlerts:Bool, tapCallBack: (() -> Void)? = nil) {
showAlert(dismissPreviousAlerts, alertBlock: { () -> Void in
RMessage.showNotification(withTitle: message, subtitle: subtitle, iconImage: image, type: .normal, customTypeName: nil, duration: 5, callback: tapCallBack, buttonTitle: nil, buttonCallback: nil, at: .bottom, canBeDismissedByUser: true)
})
}

@objc func showAlert(_ dismissPreviousAlerts:Bool, alertBlock: @escaping () -> Void) {
DispatchQueue.main.async {
Expand Down
6 changes: 5 additions & 1 deletion Wikipedia/Localizations/en.lproj/Localizable.strings
Expand Up @@ -998,21 +998,25 @@
"talk-page-new-topic-body-placeholder-text" = "Compose new discussion";
"talk-page-new-topic-success-text" = "Your discussion was successfully published";
"talk-page-new-topic-title" = "New discussion";
"talk-page-open-in-web" = "Read in web";
"talk-page-page-info" = "Page information";
"talk-page-permanent-link" = "Permanent link";
"talk-page-publish-terms-and-licenses" = "By saving changes, you agree to the $1Terms of Use$2, and agree to release your contribution under the $3CC BY-SA 3.0$4 and the $5GFDL$6 licenses.";
"talk-page-read-in-web" = "Read in web";
"talk-page-related-links" = "What links here";
"talk-page-reply-button" = "Reply";
"talk-page-reply-terms-and-licenses" = "Note your reply will be automatically signed with your username. By saving changes, you agree to the $1Terms of Use$2, and agree to release your contribution under the $3CC BY-SA 3.0$4 and the $5GFDL$6 licenses.";
"talk-page-reply-title" = "Reply";
"talk-page-revision-history" = "Revision history";
"talk-page-share-button" = "Share talk page";
"talk-page-subscribe-to-topic" = "Subscribe";
"talk-page-subscribed-alert-subtitle" = "You will receive notifications about new comments in this topic.";
"talk-page-subscribed-alert-title" = "You have subscribed!";
"talk-page-title-article-talk" = "Article Talk";
"talk-page-title-user-talk" = "User Talk";
"talk-page-topic-title" = "Discussion";
"talk-page-unsubscribe-to-topic" = "Unsubscribe";
"talk-page-unsubscribed-alert-subtitle" = "You will no longer receive notifications about new comments in this topic.";
"talk-page-unsubscribed-alert-title" = "You have unsubscribed.";
"talk-page-user-about" = "About user talk pages";
"talk-page-user-contributions" = "Contributions";
"talk-pages-coffee-roll-read-more" = "Read more";
Expand Down