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-730] Pledge screen header #1033

Merged
merged 23 commits into from
Jan 17, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e5bc6b0
Disabled custom transition
Scollaco Jan 7, 2020
90a5ac2
Removed thumbnail and added new header
Scollaco Jan 7, 2020
22e467b
Fixed header styling
Scollaco Jan 9, 2020
190d31a
Changed output to return only reward title
Scollaco Jan 9, 2020
b841324
Unit tests
Scollaco Jan 9, 2020
645fd46
Added extension to set link in a attributed string
Scollaco Jan 13, 2020
62f1211
SwiftFormat
Scollaco Jan 13, 2020
cfc3c55
Alpha and cleanup
Scollaco Jan 13, 2020
c70b0bd
Snapshots
Scollaco Jan 13, 2020
1423dbe
Merge branch 'master' into NT-730_pledge-screen-header
Scollaco Jan 13, 2020
d242773
Added minimumScalefactor to label
Scollaco Jan 13, 2020
45a2774
Merge branch 'NT-730_pledge-screen-header' of https://github.com/kick…
Scollaco Jan 13, 2020
bd88fdc
Fixed bug that wasn't showing estimated delivery info for digital rew…
Scollaco Jan 14, 2020
965adc9
Merge branch 'master' into NT-730_pledge-screen-header
Scollaco Jan 14, 2020
19b2259
Deleted custom animation
Scollaco Jan 15, 2020
eabf393
TextView no longer uses checkoutAttributedLink
Scollaco Jan 15, 2020
1b8c91d
Merge branch 'NT-730_pledge-screen-header' of https://github.com/kick…
Scollaco Jan 15, 2020
22a9555
Deleted unused extension
Scollaco Jan 16, 2020
e18be1c
Merge branch 'master' into NT-730_pledge-screen-header
Scollaco Jan 16, 2020
c73910c
Changed attributed initialization to match design style
Scollaco Jan 16, 2020
0e2c13a
Merge branch 'NT-730_pledge-screen-header' of https://github.com/kick…
Scollaco Jan 16, 2020
0216735
Snapshots
Scollaco Jan 16, 2020
9dc6c53
Merge branch 'master' into NT-730_pledge-screen-header
Scollaco Jan 17, 2020
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
370 changes: 81 additions & 289 deletions Kickstarter-iOS/Views/Controllers/PledgeDescriptionViewController.swift

Large diffs are not rendered by default.

This file was deleted.

23 changes: 5 additions & 18 deletions Kickstarter-iOS/Views/Controllers/PledgeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -483,28 +483,15 @@ extension PledgeViewController: PledgeShippingLocationViewControllerDelegate {
// MARK: - RewardPledgeTransitionAnimatorDelegate

extension PledgeViewController: RewardPledgeTransitionAnimatorDelegate {
func beginTransition(_ operation: UINavigationController.Operation) {
self.descriptionViewController.beginTransition(operation)
}

func snapshotData(withContainerView view: UIView) -> RewardPledgeTransitionSnapshotData? {
return self.descriptionViewController.snapshotData(withContainerView: view)
}
func beginTransition(_: UINavigationController.Operation) {}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Instead of deleting all of this code, I decided to keep this structure here since we discussed in standup that we may revisit the custom animation in an Investment Day.

Copy link
Contributor

Choose a reason for hiding this comment

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

On second thought I think we should remove the animation, I think it's unlikely we'll make it work with this new layout.


func destinationFrameData(withContainerView view: UIView) -> RewardPledgeTransitionDestinationFrameData? {
guard let (destination, mask) = self.descriptionViewController
.destinationFrameData(withContainerView: view)
else { return nil }
func snapshotData(withContainerView _: UIView) -> RewardPledgeTransitionSnapshotData? { return nil }

let offsetDestination = destination
.offsetBy(dx: 0, dy: -self.view.safeAreaInsets.top)

return (offsetDestination, mask)
func destinationFrameData(withContainerView _: UIView) -> RewardPledgeTransitionDestinationFrameData? {
return nil
}

func endTransition(_ operation: UINavigationController.Operation) {
self.descriptionViewController.endTransition(operation)
}
func endTransition(_: UINavigationController.Operation) {}
}

// MARK: - PledgeViewControllerMessageDisplaying
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ extension RewardPledgeNavigationController: UINavigationControllerDelegate {
) -> UIViewControllerAnimatedTransitioning? {
switch (operation, fromVC, toVC) {
case (.push, is RewardPledgeTransitionAnimatorDelegate, is PledgeViewController):
return RewardPledgePushTransitionAnimator()
return nil
case (.pop, is PledgeViewController, is RewardPledgeTransitionAnimatorDelegate):
return nil
default:
Expand Down
12 changes: 8 additions & 4 deletions Kickstarter.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,6 @@
8A8099F822E2156E00373E66 /* RewardPledgeNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8099F722E2156E00373E66 /* RewardPledgeNavigationController.swift */; };
8A8099FA22E2159300373E66 /* RewardPledgeTransitionAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8099F922E2159300373E66 /* RewardPledgeTransitionAnimator.swift */; };
8A8099FD22E2172D00373E66 /* UISpringTimingParameters+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8099FB22E2172900373E66 /* UISpringTimingParameters+Convenience.swift */; };
8A8099FF22E21F9700373E66 /* PledgeDescriptionViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8099FE22E21F9700373E66 /* PledgeDescriptionViewControllerTests.swift */; };
8AA117F323A414BF00F7E339 /* Qualtrics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AD7953123A286D800998C79 /* Qualtrics.framework */; };
8AA117F523A4160800F7E339 /* MockQualtricsResultType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AA117F423A4160800F7E339 /* MockQualtricsResultType.swift */; };
8AA5248F2384CA7900FD52CF /* EditorialProjectsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AA5248E2384CA7900FD52CF /* EditorialProjectsViewController.swift */; };
Expand Down Expand Up @@ -1198,6 +1197,8 @@
D6B9F90A22035840003282A5 /* Author.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B9F90922035840003282A5 /* Author.swift */; };
D6B9F943220358D1003282A5 /* AuthorTemplates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B9F942220358D1003282A5 /* AuthorTemplates.swift */; };
D6B9F94522035E34003282A5 /* AuthorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B9F94422035E34003282A5 /* AuthorTests.swift */; };
D6BD66B323CCC9A8008694BB /* NSAttributedString+Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BD66B223CCC9A8008694BB /* NSAttributedString+Link.swift */; };
D6BD66B523CCCA51008694BB /* NSAttributedStringLinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BD66B423CCCA51008694BB /* NSAttributedStringLinkTests.swift */; };
D6C3845B210B9AC400ADB671 /* SettingsNewslettersTopCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C38459210B9AC400ADB671 /* SettingsNewslettersTopCell.swift */; };
D6C3845C210B9AC400ADB671 /* SettingsNewslettersTopCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6C3845A210B9AC400ADB671 /* SettingsNewslettersTopCell.xib */; };
D6C9A20E1F755FE200981E64 /* GraphSchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C9A20D1F755FE200981E64 /* GraphSchemaTests.swift */; };
Expand Down Expand Up @@ -1794,7 +1795,6 @@
8A8099F722E2156E00373E66 /* RewardPledgeNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RewardPledgeNavigationController.swift; sourceTree = "<group>"; };
8A8099F922E2159300373E66 /* RewardPledgeTransitionAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RewardPledgeTransitionAnimator.swift; sourceTree = "<group>"; };
8A8099FB22E2172900373E66 /* UISpringTimingParameters+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UISpringTimingParameters+Convenience.swift"; sourceTree = "<group>"; };
8A8099FE22E21F9700373E66 /* PledgeDescriptionViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PledgeDescriptionViewControllerTests.swift; sourceTree = "<group>"; };
8AA117F423A4160800F7E339 /* MockQualtricsResultType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockQualtricsResultType.swift; sourceTree = "<group>"; };
8AA5248E2384CA7900FD52CF /* EditorialProjectsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorialProjectsViewController.swift; sourceTree = "<group>"; };
8AA524902384CAAC00FD52CF /* EditorialProjectsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorialProjectsViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2563,6 +2563,8 @@
D6B9F942220358D1003282A5 /* AuthorTemplates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorTemplates.swift; sourceTree = "<group>"; };
D6B9F94422035E34003282A5 /* AuthorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorTests.swift; sourceTree = "<group>"; };
D6B9FA1422089C05003282A5 /* SelectCurrencyViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectCurrencyViewControllerTests.swift; sourceTree = "<group>"; };
D6BD66B223CCC9A8008694BB /* NSAttributedString+Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Link.swift"; sourceTree = "<group>"; };
D6BD66B423CCCA51008694BB /* NSAttributedStringLinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSAttributedStringLinkTests.swift; sourceTree = "<group>"; };
D6C38459210B9AC400ADB671 /* SettingsNewslettersTopCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsNewslettersTopCell.swift; sourceTree = "<group>"; };
D6C3845A210B9AC400ADB671 /* SettingsNewslettersTopCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsNewslettersTopCell.xib; sourceTree = "<group>"; };
D6C9A20D1F755FE200981E64 /* GraphSchemaTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphSchemaTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3180,7 +3182,6 @@
3751E4282335871600047E9A /* PledgeAmountViewControllerTests.swift */,
7748438322D8DE8200508C9B /* PledgeContinueViewController.swift */,
D79A054A225E9B6B004BC6A8 /* PledgeDescriptionViewController.swift */,
8A8099FE22E21F9700373E66 /* PledgeDescriptionViewControllerTests.swift */,
D6D4425C22C276DF0070C3AF /* PledgePaymentMethodsViewController.swift */,
37059842226F79A700BDA6E3 /* PledgeShippingLocationViewController.swift */,
8A4DDAB22373427000ADE31D /* PledgeStatusLabelView.swift */,
Expand Down Expand Up @@ -3321,6 +3322,8 @@
A7ED1F1B1E830FDC00BFFA01 /* NavigationTests.swift */,
59E877371DC9419700BCD1F7 /* Newsletter.swift */,
A707BAD51CFFAB9400653B2F /* Notifications.swift */,
D6BD66B223CCC9A8008694BB /* NSAttributedString+Link.swift */,
D6BD66B423CCCA51008694BB /* NSAttributedStringLinkTests.swift */,
A7C725911C85D36D005A016B /* NSBundleType.swift */,
37D99C2222247F4A008EF839 /* NSBundleType+Tests.swift */,
A78537F71CB5803B00385B73 /* NSHTTPCookieStorageType.swift */,
Expand Down Expand Up @@ -4866,6 +4869,7 @@
A73379481D0E36CA00C91445 /* Fonts.swift in Sources */,
370F52B3225426C700F159B9 /* UIApplication.swift in Sources */,
8A8099FD22E2172D00373E66 /* UISpringTimingParameters+Convenience.swift in Sources */,
D6BD66B323CCC9A8008694BB /* NSAttributedString+Link.swift in Sources */,
D64DDCDD235616B500DE0EA9 /* ManagePledgePaymentMethodViewModel.swift in Sources */,
015572731E79C4FF005FB8CC /* BackerDashboardProjectCellViewModel.swift in Sources */,
8016BFE81D0F582D00067956 /* String+Whitespace.swift in Sources */,
Expand Down Expand Up @@ -5215,6 +5219,7 @@
D78E039022930DF80043E92F /* PledgeCTAContainerViewViewModelTests.swift in Sources */,
D6B4F00021079F750079159D /* SettingsNewslettersCellViewModelTests.swift in Sources */,
A7ED1FE71E831C5C00BFFA01 /* FacebookConfirmationViewModelTests.swift in Sources */,
D6BD66B523CCCA51008694BB /* NSAttributedStringLinkTests.swift in Sources */,
A7ED1FFE1E831C5C00BFFA01 /* DeprecatedRewardCellViewModelTests.swift in Sources */,
D04AACA9218BB72100CF713E /* LoadingBarButtonItemViewModelTests.swift in Sources */,
8A4503F6234BEDD4008309EC /* PledgeViewContextTests.swift in Sources */,
Expand Down Expand Up @@ -5591,7 +5596,6 @@
015102AE1F1947CB0006C0FC /* MessageThreadsDataSourceTests.swift in Sources */,
774A76F520D98EEF0012A71F /* BetaToolsViewControllerTests.swift in Sources */,
D033E2C322A05B7400464E43 /* MockApplication.swift in Sources */,
8A8099FF22E21F9700373E66 /* PledgeDescriptionViewControllerTests.swift in Sources */,
A7ED20541E8323E900BFFA01 /* ProjectPamphletContentViewControllerTests.swift in Sources */,
1611EF6A23B2773A0051CDCC /* MockUUID.swift in Sources */,
D643E7C82346426E00C02C15 /* ManagePledgeViewControllerTests.swift in Sources */,
Expand Down
13 changes: 13 additions & 0 deletions Library/NSAttributedString+Link.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

public extension NSAttributedString {
func setAsLink(textToFind: String, linkURL: String) -> NSAttributedString {
let string = NSMutableAttributedString(attributedString: self)
let foundRange = string.mutableString.range(of: textToFind)
if foundRange.location != NSNotFound {
string.addAttribute(.link, value: linkURL, range: foundRange)
return string
}
return self
}
}
24 changes: 24 additions & 0 deletions Library/NSAttributedStringLinkTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@testable import Library
import XCTest

final class NSAttributedString_LinkTests: TestCase {
func testAttributedLink() {
let string = "My special string with "
let linkString = "link"

let fullString = string + linkString

let attributed = NSAttributedString(string: fullString)
.setAsLink(textToFind: linkString, linkURL: "https://ksr.com")

let linkRange = (fullString as NSString).range(of: linkString)

let linkAttributes = attributed.attributes(
at: linkRange.location,
longestEffectiveRange: nil,
in: linkRange
)

XCTAssertEqual(linkAttributes[NSAttributedString.Key.link] as? String, "https://ksr.com")
}
}
16 changes: 12 additions & 4 deletions Library/ViewModels/PledgeDescriptionViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ public protocol PledgeDescriptionViewModelInputs {
}

public protocol PledgeDescriptionViewModelOutputs {
var configureRewardCardViewWithData: Signal<(Project, Either<Reward, Backing>), Never> { get }
var estimatedDeliveryStackViewIsHidden: Signal<Bool, Never> { get }
var estimatedDeliveryText: Signal<String, Never> { get }
var popViewController: Signal<(), Never> { get }
var presentTrustAndSafety: Signal<Void, Never> { get }
var rewardTitle: Signal<String, Never> { get }
}

public protocol PledgeDescriptionViewModelType {
Expand All @@ -32,10 +33,16 @@ public final class PledgeDescriptionViewModel: PledgeDescriptionViewModelType,
.skipNil()
.map { Format.date(secondsInUTC: $0, template: DateFormatter.monthYear, timeZone: UTCTimeZone) }

self.estimatedDeliveryStackViewIsHidden = self.configDataProperty.signal
.skipNil()
.map(second)
.map { $0.shipping.enabled }
.negate()

self.presentTrustAndSafety = self.learnMoreTappedProperty.signal
self.configureRewardCardViewWithData = self.configDataProperty.signal
self.rewardTitle = self.configDataProperty.signal
.skipNil()
.map { project, reward in (project, .init(left: reward)) }
.map { _, reward in reward.title ?? Strings.Back_it_because_you_believe_in_it() }
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it make sense to check if title is nil and also whether its noReward? Just to be sure 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The NoReward only contains some of the properties of the Reward object, and it doesn't have the title. So the title, in this case, will always be nil.


self.popViewController = self.rewardCardTappedSignal
}
Expand All @@ -55,10 +62,11 @@ public final class PledgeDescriptionViewModel: PledgeDescriptionViewModelType,
self.rewardCardTappedObserver.send(value: ())
}

public let configureRewardCardViewWithData: Signal<(Project, Either<Reward, Backing>), Never>
public let estimatedDeliveryStackViewIsHidden: Signal<Bool, Never>
public let estimatedDeliveryText: Signal<String, Never>
public let popViewController: Signal<(), Never>
public let presentTrustAndSafety: Signal<Void, Never>
public let rewardTitle: Signal<String, Never>

public var inputs: PledgeDescriptionViewModelInputs { return self }
public var outputs: PledgeDescriptionViewModelOutputs { return self }
Expand Down
39 changes: 39 additions & 0 deletions Library/ViewModels/PledgeDescriptionViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@ import XCTest
internal final class PledgeDescriptionViewModelTests: TestCase {
private let vm: PledgeDescriptionViewModelType = PledgeDescriptionViewModel()

private let estimatedDeliveryStackViewIsHidden = TestObserver<Bool, Never>()
private let estimatedDeliveryText = TestObserver<String, Never>()
private let popViewController = TestObserver<(), Never>()
private let presentTrustAndSafety = TestObserver<Void, Never>()
private let rewardTitle = TestObserver<String, Never>()

override func setUp() {
super.setUp()

self.vm.outputs.estimatedDeliveryStackViewIsHidden.observe(
self.estimatedDeliveryStackViewIsHidden.observer
)
self.vm.outputs.estimatedDeliveryText.observe(self.estimatedDeliveryText.observer)
self.vm.outputs.popViewController.observe(self.popViewController.observer)
self.vm.outputs.presentTrustAndSafety.observe(self.presentTrustAndSafety.observer)
self.vm.outputs.rewardTitle.observe(self.rewardTitle.observer)
}

func testEstimatedDeliveryDate() {
Expand Down Expand Up @@ -46,4 +52,37 @@ internal final class PledgeDescriptionViewModelTests: TestCase {

self.popViewController.assertValueCount(1)
}

func testRewardTitle_WithReward() {
let reward = Reward.template
|> Reward.lens.title .~ "iPhone 15"

self.vm.inputs.configureWith(data: (.template, reward))

self.rewardTitle.assertValue("iPhone 15")
}

func testRewardTitle_WithNoReward() {
self.vm.inputs.configureWith(data: (.template, .noReward))

self.rewardTitle.assertValue("Back it because you believe in it.")
}

func testEstimatedDeliveryStackViewIsHidden_ShippingEnabled() {
let reward = Reward.template
|> Reward.lens.shipping.enabled .~ true

self.vm.inputs.configureWith(data: (.template, reward))

self.estimatedDeliveryStackViewIsHidden.assertValue(false)
}

func testEstimatedDeliveryStackViewIsHidden_ShippingDisabled() {
let reward = Reward.template
|> Reward.lens.shipping.enabled .~ false

self.vm.inputs.configureWith(data: (.template, reward))

self.estimatedDeliveryStackViewIsHidden.assertValue(true)
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.