Skip to content

Commit

Permalink
Merge pull request #4312 from wikimedia/T311639-subscription
Browse files Browse the repository at this point in the history
Add banner to subscription action
  • Loading branch information
tonisevener committed Sep 9, 2022
2 parents c9f9aa0 + 05ca6b1 commit 7a396ff
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 64 deletions.
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.")
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

0 comments on commit 7a396ff

Please sign in to comment.