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

[NT-278] Manage pledge menu #846

Merged
merged 14 commits into from
Sep 23, 2019
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
"Manage_your_pledge" = "Manage your pledge";
"Manage_your_pledge_below" = "Manage your pledge below";
"Manage_your_reward" = "Manage your reward";
"Menu" = "Menu";
"Message_backer" = "Message backer";
"Message_banner.accessibility.Double_tap_to_dismiss" = "Double tap to dismiss.";
"Message_creator" = "Message creator";
Expand Down
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
"Manage_your_pledge" = "Meinen Beitrag verwalten";
"Manage_your_pledge_below" = "Folgenden Beitrag verwalten";
"Manage_your_reward" = "Belohnung verwalten";
"Menu" = "Menü";
"Message_backer" = "Nachricht an Unterstützer senden";
"Message_banner.accessibility.Double_tap_to_dismiss" = "Zweimal antippen, um Banner auszublenden.";
"Message_creator" = "Nachricht an Projektgründer senden";
Expand Down
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
"Manage_your_pledge" = "Administra tu contribución";
"Manage_your_pledge_below" = "Administra tu contribución:";
"Manage_your_reward" = "Administra tu recompensa";
"Menu" = "Menú";
"Message_backer" = "Enviar mensaje a patrocinador";
"Message_banner.accessibility.Double_tap_to_dismiss" = "Toca dos veces para descartar.";
"Message_creator" = "Enviar mensaje al creador";
Expand Down
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
"Manage_your_pledge" = "Gérer mon engagement";
"Manage_your_pledge_below" = "Gérer mon engagement";
"Manage_your_reward" = "Gérer votre récompense";
"Menu" = "Menu";
"Message_backer" = "Envoyer un message au contributeur";
"Message_banner.accessibility.Double_tap_to_dismiss" = "Cliquez deux fois pour faire disparaître ce message.";
"Message_creator" = "Envoyer un message au créateur";
Expand Down
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
"Manage_your_pledge" = "プレッジを変更";
"Manage_your_pledge_below" = "以下のプレッジを変更";
"Manage_your_reward" = "リワードの管理";
"Menu" = "メニュー";
"Message_backer" = "バッカーにメッセージする";
"Message_banner.accessibility.Double_tap_to_dismiss" = "却下するにはダブルタップ。";
"Message_creator" = "クリエーターにメッセージする";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ final class ManageViewPledgeViewController: UIViewController {
)
}()

private lazy var editButton: UIBarButtonItem = {
private lazy var menuButton: UIBarButtonItem = {
UIBarButtonItem(
image: UIImage(named: "icon--more-menu"),
style: .plain,
target: self,
action: #selector(ManageViewPledgeViewController.editButtonTapped)
action: #selector(ManageViewPledgeViewController.menuButtonTapped)
)
}()

Expand Down Expand Up @@ -66,7 +66,7 @@ final class ManageViewPledgeViewController: UIViewController {

_ = self.navigationItem
?|> \.leftBarButtonItem .~ self.closeButton
?|> \.rightBarButtonItem .~ self.editButton
?|> \.rightBarButtonItem .~ self.menuButton

_ = (self.rootScrollView, self.view)
|> ksr_addSubviewToParent()
Expand Down Expand Up @@ -94,6 +94,9 @@ final class ManageViewPledgeViewController: UIViewController {
|> \.accessibilityLabel %~ { _ in Strings.Dismiss() }
|> \.width .~ Styles.minTouchSize.width

_ = self.menuButton
|> \.accessibilityLabel %~ { _ in Strings.Menu() }

_ = self.rootScrollView
|> rootScrollViewStyle

Expand Down Expand Up @@ -125,6 +128,12 @@ final class ManageViewPledgeViewController: UIViewController {
self.viewModel.outputs.configureRewardSummaryView
.observeForUI()
.observeValues { _ in }

self.viewModel.outputs.showActionSheetMenuWithOptions
.observeForControllerAction()
.observeValues { [weak self] options in
self?.showActionSheetMenuWithOptions(options)
}
}

// MARK: - Configuration
Expand Down Expand Up @@ -156,15 +165,44 @@ final class ManageViewPledgeViewController: UIViewController {

// MARK: Actions

@objc private func editButtonTapped() {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
@objc private func menuButtonTapped() {
self.viewModel.inputs.menuButtonTapped()
}

actionSheet.addAction(
UIAlertAction(title: Strings.Contact_creator(), style: .default)
private func showActionSheetMenuWithOptions(_ options: [ManagePledgeAlertAction]) {
let actionSheet = UIAlertController.alert(
title: Strings.Select_an_option(),
preferredStyle: .actionSheet,
barButtonItem: self.menuButton
Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, this works and makes it properly relocate when rotating the device 👍

)

options.forEach { option in
let title: String

switch option {
case .updatePledge:
title = Strings.Update_pledge()
case .changePaymentMethod:
title = Strings.Change_payment_method()
case .chooseAnotherReward:
title = Strings.Choose_another_reward()
case .contactCreator:
title = Strings.Contact_creator()
case .cancelPledge:
title = Strings.Cancel_pledge()
}

let style: UIAlertAction.Style = option == .cancelPledge ? .destructive : .default

actionSheet.addAction(
UIAlertAction(title: title, style: style)
)
}

actionSheet.addAction(
UIAlertAction(title: Strings.Cancel(), style: .cancel)
)

self.present(actionSheet, animated: true)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ internal final class ProjectPamphletViewControllerTests: TestCase {
parent.view.frame.size.height = device == .pad ? 1_200 : parent.view.frame.size.height

scheduler.run()

FBSnapshotVerifyView(vc.view, identifier: "lang_\(language)_device_\(device)")
}
}
Expand Down
17 changes: 17 additions & 0 deletions Library/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4583,6 +4583,23 @@ with friends."
substitutions: [:]
)
}
/**
"Menu"

- **en**: "Menu"
- **de**: "Menü"
- **es**: "Menú"
- **fr**: "Menu"
- **ja**: "メニュー"
*/
public static func Menu() -> String {
return localizedString(
key: "Menu",
defaultValue: "Menu",
count: nil,
substitutions: [:]
)
}
/**
"Message backer"

Expand Down
4 changes: 3 additions & 1 deletion Library/UIAlertController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public extension UIAlertController {
title: String,
message: String? = nil,
preferredStyle: UIAlertController.Style,
sourceView: UIView? = nil
sourceView: UIView? = nil,
barButtonItem: UIBarButtonItem? = nil
) -> UIAlertController {
let alert = UIAlertController(
title: title,
Expand All @@ -20,6 +21,7 @@ public extension UIAlertController {
if UIAlertController.requiresPopOverConfiguration(preferredStyle) {
alert.modalPresentationStyle = .popover
alert.popoverPresentationController?.sourceView = sourceView
alert.popoverPresentationController?.barButtonItem = barButtonItem
}

return alert
Expand Down
28 changes: 28 additions & 0 deletions Library/ViewModels/ManageViewPledgeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,25 @@ import Prelude
import ReactiveExtensions
import ReactiveSwift

public enum ManagePledgeAlertAction: CaseIterable {
case updatePledge
case changePaymentMethod
case chooseAnotherReward
case contactCreator
case cancelPledge
}

public protocol ManageViewPledgeViewModelInputs {
func configureWith(_ project: Project, reward: Reward)
func menuButtonTapped()
func viewDidLoad()
}

public protocol ManageViewPledgeViewModelOutputs {
var configurePaymentMethodView: Signal<Project, Never> { get }
var configurePledgeSummaryView: Signal<Project, Never> { get }
var configureRewardSummaryView: Signal<Reward, Never> { get }
var showActionSheetMenuWithOptions: Signal<[ManagePledgeAlertAction], Never> { get }
var title: Signal<String, Never> { get }
}

Expand All @@ -38,13 +48,30 @@ public final class ManageViewPledgeViewModel:

self.configureRewardSummaryView = projectAndReward
.map(second)

let project = projectAndReward.map(first)

self.showActionSheetMenuWithOptions = project
.takeWhen(self.menuButtonTappedSignal)
.map { project -> [ManagePledgeAlertAction] in
if project.state == .live {
return ManagePledgeAlertAction.allCases
} else {
return [.contactCreator]
}
}
}

private let (projectAndRewardSignal, projectAndRewardObserver) = Signal<(Project, Reward), Never>.pipe()
public func configureWith(_ project: Project, reward: Reward) {
self.projectAndRewardObserver.send(value: (project, reward))
}

private let (menuButtonTappedSignal, menuButtonTappedObserver) = Signal<Void, Never>.pipe()
public func menuButtonTapped() {
self.menuButtonTappedObserver.send(value: ())
}

private let (viewDidLoadSignal, viewDidLoadObserver) = Signal<(), Never>.pipe()
public func viewDidLoad() {
self.viewDidLoadObserver.send(value: ())
Expand All @@ -53,6 +80,7 @@ public final class ManageViewPledgeViewModel:
public let configurePaymentMethodView: Signal<Project, Never>
public let configurePledgeSummaryView: Signal<Project, Never>
public let configureRewardSummaryView: Signal<Reward, Never>
public let showActionSheetMenuWithOptions: Signal<[ManagePledgeAlertAction], Never>
public let title: Signal<String, Never>

public var inputs: ManageViewPledgeViewModelInputs { return self }
Expand Down
30 changes: 30 additions & 0 deletions Library/ViewModels/ManageViewPledgeViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ internal final class ManageViewPledgeViewModelTests: TestCase {
private let configurePaymentMethodView = TestObserver<Project, Never>()
private let configurePledgeSummaryView = TestObserver<Project, Never>()
private let configureRewardSummaryView = TestObserver<Reward, Never>()
private let showActionSheetMenuWithOptions = TestObserver<[ManagePledgeAlertAction], Never>()
private let title = TestObserver<String, Never>()

override func setUp() {
Expand All @@ -23,6 +24,7 @@ internal final class ManageViewPledgeViewModelTests: TestCase {
.observe(self.configurePledgeSummaryView.observer)
self.vm.outputs.configureRewardSummaryView
.observe(self.configureRewardSummaryView.observer)
self.vm.outputs.showActionSheetMenuWithOptions.observe(self.showActionSheetMenuWithOptions.observer)
}

func testNavigationBarTitle_LiveProject() {
Expand Down Expand Up @@ -80,4 +82,32 @@ internal final class ManageViewPledgeViewModelTests: TestCase {

self.configureRewardSummaryView.assertValue(reward)
}

func testMenuButtonTapped_WhenProject_IsLive() {
let project = Project.template
|> Project.lens.state .~ .live

self.vm.inputs.configureWith(project, reward: .template)
self.vm.inputs.viewDidLoad()

self.showActionSheetMenuWithOptions.assertDidNotEmitValue()

self.vm.inputs.menuButtonTapped()

self.showActionSheetMenuWithOptions.assertValues([ManagePledgeAlertAction.allCases])
}

func testMenuButtonTapped_WhenProject_IsNotLive() {
let project = Project.template
|> Project.lens.state .~ .successful

self.vm.inputs.configureWith(project, reward: .template)
self.vm.inputs.viewDidLoad()

self.showActionSheetMenuWithOptions.assertDidNotEmitValue()

self.vm.inputs.menuButtonTapped()

self.showActionSheetMenuWithOptions.assertValues([[.contactCreator]])
}
}