diff --git a/Demo/Components/Klimabrolet/KlimabroletData.swift b/Demo/Components/Klimabrolet/KlimabroletData.swift new file mode 100644 index 0000000000..422a6ff34f --- /dev/null +++ b/Demo/Components/Klimabrolet/KlimabroletData.swift @@ -0,0 +1,41 @@ +// +// Copyright © 2019 FINN AS. All rights reserved. +// + +import FinniversKit + +struct KlimabroletData { + static let campaignURL = URL(string: "https://klimabrolet.no") + + struct ViewModel: KlimabroletViewModel { + let title: String = "Bli med og BRØØØL!" + let subtitle: String = "30 August kl. 15.00" + let bodyText: String = "Barn og unge over hele verden har samlet seg i gatene til støtte for miljøet. Ikke la dem stå alene. Bli med og brøl for klimaet!" + let readMoreButtonTitle: String = "Les mer om Klimabrølet" + let acceptButtonTitle: String = "Bli med på Klimabrølet!" + let declineButtonTitle: String = "Nei takk" + } + + struct Event { + let name: String + let url: URL? = URL(string: "https://klimabrolet.no/faq") + } + + static let events: [Event] = [ + Event(name: "Klimabrølet Oslo"), + Event(name: "Klimabrølet Tønsberg"), + Event(name: "Klimabrølet Stavanger"), + Event(name: "Klimabrølet Bergen"), + Event(name: "Klimabrølet Røros"), + Event(name: "Klimabrølet Trondheim"), + Event(name: "Klimabrølet Henningsvær"), + Event(name: "Klimabrølet Svalbard") + ] +} + +extension KlimabroletData.Event: BasicTableViewCellViewModel { + var title: String { return name } + var subtitle: String? { return nil } + var detailText: String? { return nil } + var hasChevron: Bool { return false } +} diff --git a/Demo/Components/Klimabrolet/KlimabroletDemoViewController.swift b/Demo/Components/Klimabrolet/KlimabroletDemoViewController.swift new file mode 100644 index 0000000000..6a294e09df --- /dev/null +++ b/Demo/Components/Klimabrolet/KlimabroletDemoViewController.swift @@ -0,0 +1,106 @@ +// +// Copyright © 2019 FINN AS. All rights reserved. +// + +import FinniversKit + +class KlimabroletDemoViewController: DemoViewController { + private lazy var klimabroletView: KlimabroletView = { + let view = KlimabroletView(withAutoLayout: true) + view.configure(with: KlimabroletData.ViewModel()) + view.delegate = self + return view + }() + + private lazy var klimabroletViewController: UIViewController = { + let controller = UIViewController() + controller.view.addSubview(klimabroletView) + controller.setNeedsStatusBarAppearanceUpdate() + klimabroletView.fillInSuperview() + + return controller + }() + + private lazy var eventListViewController: KlimabroletEventsDemoViewController = { + let controller = KlimabroletEventsDemoViewController(style: .plain) + controller.delegate = self + return controller + }() + + private lazy var innerNavigationController: UINavigationController = { + let navigation = UINavigationController(rootViewController: klimabroletViewController) + navigation.view.translatesAutoresizingMaskIntoConstraints = false + navigation.setNavigationBarHidden(true, animated: false) + navigation.view.layer.cornerRadius = 20 + navigation.view.clipsToBounds = true + navigation.delegate = self + + return navigation + }() + + override func viewDidLoad() { + super.viewDidLoad() + playgroundView.backgroundColor = .black + + addChild(innerNavigationController) + innerNavigationController.didMove(toParent: self) + view.addSubview(innerNavigationController.view) + + NSLayoutConstraint.activate([ + innerNavigationController.view.widthAnchor.constraint(equalToConstant: 320), + innerNavigationController.view.heightAnchor.constraint(equalToConstant: 536), + innerNavigationController.view.centerXAnchor.constraint(equalTo: view.centerXAnchor), + innerNavigationController.view.centerYAnchor.constraint(equalTo: view.centerYAnchor) + ]) + } + + private func close() { + State.lastSelectedIndexPath = nil + dismiss(animated: true, completion: nil) + } +} + +extension KlimabroletDemoViewController: KlimabroletViewDelegate { + func klimabroletViewDidSelectReadMore(_ view: KlimabroletView) { + guard let url = KlimabroletData.campaignURL else { + return + } + + UIApplication.shared.open(url) + } + + func klimabroletViewDidSelectAccept(_ view: KlimabroletView) { + innerNavigationController.pushViewController(eventListViewController, animated: true) + } + + func klimabroletViewDidSelectDecline(_ view: KlimabroletView) { + close() + } + + func klimabroletViewDidSelectClose(_ view: KlimabroletView) { + close() + } +} + +extension KlimabroletDemoViewController: KlimabroletEventsDemoViewControllerDelegate { + func eventList(_ eventListViewController: KlimabroletEventsDemoViewController, didSelect event: KlimabroletData.Event) { + guard let url = event.url else { + return + } + + UIApplication.shared.open(url) + } + + func eventListDidSelectClose(_ eventListViewController: KlimabroletEventsDemoViewController) { + close() + } +} + +extension KlimabroletDemoViewController: UINavigationControllerDelegate { + func navigationController( + _ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool + ) { + let needsNavigationBarHidden = viewController == klimabroletViewController + innerNavigationController.setNavigationBarHidden(needsNavigationBarHidden, animated: true) + } +} diff --git a/Demo/Components/Klimabrolet/KlimabroletEventsDemoViewController.swift b/Demo/Components/Klimabrolet/KlimabroletEventsDemoViewController.swift new file mode 100644 index 0000000000..038e4ea4fc --- /dev/null +++ b/Demo/Components/Klimabrolet/KlimabroletEventsDemoViewController.swift @@ -0,0 +1,85 @@ +// +// Copyright © 2019 FINN AS. All rights reserved. +// + +import FinniversKit + +protocol KlimabroletEventsDemoViewControllerDelegate: AnyObject { + func eventList(_ eventListViewController: KlimabroletEventsDemoViewController, didSelect event: KlimabroletData.Event) + func eventListDidSelectClose(_ eventListViewController: KlimabroletEventsDemoViewController) +} + +class KlimabroletEventsDemoViewController: UITableViewController { + let events: [KlimabroletData.Event] = KlimabroletData.events + + weak var delegate: KlimabroletEventsDemoViewControllerDelegate? + + private lazy var closeButton: UIButton = { + let button = UIButton(type: .custom) + button.translatesAutoresizingMaskIntoConstraints = false + button.setImage(UIImage(named: .cross).withRenderingMode(.alwaysTemplate), for: .normal) + button.tintColor = .stone + button.addTarget(self, action: #selector(handleCloseButtonTap), for: .touchUpInside) + return button + }() + + override init(style: UITableView.Style) { + super.init(style: style) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + title = "Velg arrangement" + setupNavigationBar() + navigationItem.rightBarButtonItem = UIBarButtonItem(customView: closeButton) + NSLayoutConstraint.activate([ + closeButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 12), + closeButton.heightAnchor.constraint(greaterThanOrEqualToConstant: 12), + ]) + tableView.register(BasicTableViewCell.self) + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return events.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeue(BasicTableViewCell.self, for: indexPath) + let model = events[indexPath.row] + cell.configure(with: model) + cell.selectionStyle = .default + return cell + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 48 + } + + override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + let view = UIView() + view.backgroundColor = .milk + return view + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let event = events[indexPath.row] + delegate?.eventList(self, didSelect: event) + } + + private func setupNavigationBar() { + guard let navigationBar = navigationController?.navigationBar else { + return + } + + navigationBar.isTranslucent = false + navigationBar.setBackgroundImage(UIImage(), for: .default) + navigationBar.shadowImage = UIImage() + } + + @objc private func handleCloseButtonTap() { + delegate?.eventListDidSelectClose(self) + } +} diff --git a/Demo/Demo/Demo.swift b/Demo/Demo/Demo.swift index be0415d72e..5371fee3c0 100644 --- a/Demo/Demo/Demo.swift +++ b/Demo/Demo/Demo.swift @@ -55,6 +55,7 @@ public enum ComponentViews: String, CaseIterable { case feedbackView case happinessRating case earthHour + case klimabrolet case stepIndicator case nativeAdvert case callout @@ -129,6 +130,8 @@ public enum ComponentViews: String, CaseIterable { return DemoViewController(withDismissButton: true) case .earthHour: return DemoViewController() + case .klimabrolet: + return KlimabroletDemoViewController(usingDoubleTapToDismiss: false) case .stepIndicator: return DemoViewController(withDismissButton: true) case .nativeAdvert: diff --git a/FinniversKit.xcodeproj/project.pbxproj b/FinniversKit.xcodeproj/project.pbxproj index e673db77ba..b7bf495d9f 100644 --- a/FinniversKit.xcodeproj/project.pbxproj +++ b/FinniversKit.xcodeproj/project.pbxproj @@ -240,15 +240,22 @@ 9A37D36854B78610AFEADD5C /* UITableViewCellExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A37DF20BB7306D8D1A25593 /* UITableViewCellExtensions.swift */; }; 9A37D6FADD7DBD952AA395F7 /* FavoriteAdTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A37D30A5DD3B5A286743DA3 /* FavoriteAdTableViewCell.swift */; }; 9A37D9EDC4E78EC664D528FE /* FeedbackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A37D9749A60B9BFD125F483 /* FeedbackView.swift */; }; - 9A37DACD70E4383536D5312B /* FeedbackDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A37D31AFA28AABED492E588 /* FeedbackDemoView.swift */; }; 9A37DC6E6F0401357C564B93 /* RemoteImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A37D61B28BC0BA6CA6110A5 /* RemoteImageView.swift */; }; 9A37DDB3353F56739B23D22B /* FavoriteAdCellDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A37DECC59A6DBC8F54A7614 /* FavoriteAdCellDemoView.swift */; }; 9B23769122DC6CEF00FCA381 /* NSLayoutAnchorExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B23769022DC6CEF00FCA381 /* NSLayoutAnchorExtensions.swift */; }; 9B238F02225B95F600B0E0C2 /* InfoboxView+Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B238F01225B95F600B0E0C2 /* InfoboxView+Style.swift */; }; + 9B239E1122E093E800A4E9D0 /* KlimabroletContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B239E1022E093E800A4E9D0 /* KlimabroletContentView.swift */; }; + 9B7D5A2B22E1A5AF001E4005 /* KlimabroletDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B7D5A2A22E1A5AF001E4005 /* KlimabroletDemoViewController.swift */; }; + 9B7D5A2D22E1B3B4001E4005 /* KlimabroletEventsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B7D5A2C22E1B3B4001E4005 /* KlimabroletEventsDemoViewController.swift */; }; + 9B9287AB22F0593700FC7B69 /* KlimabroletData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B9287AA22F0593700FC7B69 /* KlimabroletData.swift */; }; + 9B9F8C1722F07B2100298CDB /* FeedbackDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B9F8C1422F079F600298CDB /* FeedbackDemoView.swift */; }; + 9BBC8AE122DF50E5003453B6 /* KlimabroletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BBC8AE022DF50E5003453B6 /* KlimabroletView.swift */; }; 9BC33DE322D71986007CCD65 /* LoginEntryViewDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BC33DE222D71986007CCD65 /* LoginEntryViewDemoView.swift */; }; 9BC33DE922D72293007CCD65 /* LoginEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BC33DE722D721E6007CCD65 /* LoginEntryView.swift */; }; 9BC33DEB22D76405007CCD65 /* LoginEntryDialogueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BC33DEA22D76405007CCD65 /* LoginEntryDialogueView.swift */; }; 9BC33DED22D76D4F007CCD65 /* LoginEntryDemoData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BC33DEC22D76D4F007CCD65 /* LoginEntryDemoData.swift */; }; + 9BCDFC7422E09DF700A80D7F /* KlimabroletActionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BCDFC7322E09DF700A80D7F /* KlimabroletActionsView.swift */; }; + 9BCDFC7622E09E3C00A80D7F /* KlimabroletViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BCDFC7522E09E3C00A80D7F /* KlimabroletViewModel.swift */; }; 9F2130071B3637C7AD91066E /* FullscreenGalleryTransitionDestinationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F21396E3BBAE40481AB6380 /* FullscreenGalleryTransitionDestinationDelegate.swift */; }; 9F213036DE161042F54529B0 /* FullscreenGalleryTransitioningController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2134FB742B5E38B8428113 /* FullscreenGalleryTransitioningController.swift */; }; 9F21325E45E1BB6A5F076211 /* FullscreenGalleryDismissalTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2133592F1C81B96801F10C /* FullscreenGalleryDismissalTransition.swift */; }; @@ -686,10 +693,18 @@ 9A37DF20BB7306D8D1A25593 /* UITableViewCellExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITableViewCellExtensions.swift; sourceTree = ""; }; 9B23769022DC6CEF00FCA381 /* NSLayoutAnchorExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutAnchorExtensions.swift; sourceTree = ""; }; 9B238F01225B95F600B0E0C2 /* InfoboxView+Style.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InfoboxView+Style.swift"; sourceTree = ""; }; + 9B239E1022E093E800A4E9D0 /* KlimabroletContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KlimabroletContentView.swift; sourceTree = ""; }; + 9B7D5A2A22E1A5AF001E4005 /* KlimabroletDemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KlimabroletDemoViewController.swift; sourceTree = ""; }; + 9B7D5A2C22E1B3B4001E4005 /* KlimabroletEventsDemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KlimabroletEventsDemoViewController.swift; sourceTree = ""; }; + 9B9287AA22F0593700FC7B69 /* KlimabroletData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KlimabroletData.swift; sourceTree = ""; }; + 9B9F8C1422F079F600298CDB /* FeedbackDemoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedbackDemoView.swift; sourceTree = ""; }; + 9BBC8AE022DF50E5003453B6 /* KlimabroletView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KlimabroletView.swift; sourceTree = ""; }; 9BC33DE222D71986007CCD65 /* LoginEntryViewDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginEntryViewDemoView.swift; sourceTree = ""; }; 9BC33DE722D721E6007CCD65 /* LoginEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginEntryView.swift; sourceTree = ""; }; 9BC33DEA22D76405007CCD65 /* LoginEntryDialogueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginEntryDialogueView.swift; sourceTree = ""; }; 9BC33DEC22D76D4F007CCD65 /* LoginEntryDemoData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginEntryDemoData.swift; sourceTree = ""; }; + 9BCDFC7322E09DF700A80D7F /* KlimabroletActionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KlimabroletActionsView.swift; sourceTree = ""; }; + 9BCDFC7522E09E3C00A80D7F /* KlimabroletViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KlimabroletViewModel.swift; sourceTree = ""; }; 9F2133592F1C81B96801F10C /* FullscreenGalleryDismissalTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullscreenGalleryDismissalTransition.swift; sourceTree = ""; }; 9F2133D2324BEE366DBA2134 /* FullscreenGalleryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullscreenGalleryViewController.swift; sourceTree = ""; }; 9F2133F39A730EF3068C7DDA /* FullscreenGalleryDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullscreenGalleryDemoViewController.swift; sourceTree = ""; }; @@ -1357,6 +1372,7 @@ 14DC126821593B0000326DC3 /* HorizontalSlide */, CFB61372229ACA5200DE283D /* IconCollection */, CF136ACB220320DD00247B30 /* Infobox */, + 9BBC8ADC22DF4CA2003453B6 /* Klimabrolet */, 4447F6741FDB2B110033DBC1 /* Label */, 44AFCE44215839F6005984DB /* LoadingIndicator */, 89A7A63A2253376D0053D33B /* NativeAdvert */, @@ -1898,20 +1914,49 @@ path = FavoriteAdTableViewCell; sourceTree = ""; }; - 9A37DBD671995665FDBC64C4 /* Feedback */ = { + 9A37DFB4ED453062D0BED7A9 /* FavoriteAdTableViewCell */ = { isa = PBXGroup; children = ( - 9A37D31AFA28AABED492E588 /* FeedbackDemoView.swift */, + 9A37DECC59A6DBC8F54A7614 /* FavoriteAdCellDemoView.swift */, + ); + path = FavoriteAdTableViewCell; + sourceTree = ""; + }; + 9B239E0F22E093D000A4E9D0 /* Views */ = { + isa = PBXGroup; + children = ( + 9B239E1022E093E800A4E9D0 /* KlimabroletContentView.swift */, + 9BCDFC7322E09DF700A80D7F /* KlimabroletActionsView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 9B9F8C1322F079F600298CDB /* Feedback */ = { + isa = PBXGroup; + children = ( + 9B9F8C1422F079F600298CDB /* FeedbackDemoView.swift */, ); path = Feedback; sourceTree = ""; }; - 9A37DFB4ED453062D0BED7A9 /* FavoriteAdTableViewCell */ = { + 9BBC8ADC22DF4CA2003453B6 /* Klimabrolet */ = { isa = PBXGroup; children = ( - 9A37DECC59A6DBC8F54A7614 /* FavoriteAdCellDemoView.swift */, + 9B239E0F22E093D000A4E9D0 /* Views */, + 9BBC8AE022DF50E5003453B6 /* KlimabroletView.swift */, + 9BCDFC7522E09E3C00A80D7F /* KlimabroletViewModel.swift */, ); - path = FavoriteAdTableViewCell; + path = Klimabrolet; + sourceTree = ""; + }; + 9BBC8ADD22DF4D17003453B6 /* Klimabrolet */ = { + isa = PBXGroup; + children = ( + 9B7D5A2A22E1A5AF001E4005 /* KlimabroletDemoViewController.swift */, + 9B7D5A2C22E1B3B4001E4005 /* KlimabroletEventsDemoViewController.swift */, + 9B9287AA22F0593700FC7B69 /* KlimabroletData.swift */, + ); + path = Klimabrolet; sourceTree = ""; }; 9BC33DE122D7192F007CCD65 /* LoginEntry */ = { @@ -2237,6 +2282,7 @@ isa = PBXGroup; children = ( CF29845D229566E8008CD832 /* ContactFormCheckbox.swift */, + 9A37D31AFA28AABED492E588 /* FeedbackDemoView.swift */, ); name = "Recovered References"; sourceTree = ""; @@ -2297,6 +2343,7 @@ CF8F021421DCC5B2004C4042 /* Components */ = { isa = PBXGroup; children = ( + 9BBC8ADD22DF4D17003453B6 /* Klimabrolet */, 083349EA21EF24AE000E68D3 /* BottomSheet */, CF8F021D21DCC691004C4042 /* Broadcast */, CF8F021E21DCC6A0004C4042 /* Button */, @@ -2306,7 +2353,7 @@ AA7A854F22258A0B00AF5F42 /* Dialogue */, 0884C6CA22B7B5DA0015474D /* Disclaimer */, CF7C460B22257AE1001FB92C /* EarthHour */, - 9A37DBD671995665FDBC64C4 /* Feedback */, + 9B9F8C1322F079F600298CDB /* Feedback */, 08F0D3F5222691F000968256 /* HappinessRating */, CF8F021521DCC5DA004C4042 /* HorizontalSlide */, CFB61377229ACB6200DE283D /* IconCollection */, @@ -3324,6 +3371,7 @@ 44B94FE522E0AB420078A23C /* TweakingOptionsTableViewController.swift in Sources */, 44587023213FA362009187BE /* LoginViewDefaultData.swift in Sources */, 44B94FE722E0AB6C0078A23C /* TweakingOptionCell.swift in Sources */, + 9B9287AB22F0593700FC7B69 /* KlimabroletData.swift in Sources */, CF848C2F21C7E3010086530E /* CogWheelButtonDemoView.swift in Sources */, 44587025213FA362009187BE /* LoginViewDemoView.swift in Sources */, 141F08C62123110B001DB145 /* DemoHelpers.swift in Sources */, @@ -3357,12 +3405,14 @@ CFF9727921C3F80D00C85238 /* BannerTransparencyInfoDefaultData.swift in Sources */, 081F51BA222930C500026C84 /* TextViewDemoView.swift in Sources */, CF13D6D42292E3030087DA37 /* PhaseListViewDemo.swift in Sources */, + 9B9F8C1722F07B2100298CDB /* FeedbackDemoView.swift in Sources */, CFE43E50219B150D00D3D5F7 /* FrontPageViewDefaultData.swift in Sources */, AA864B37222D6F3F00BAE95A /* DialogueViewController.swift in Sources */, 44AEFC2422E722FC00D3C307 /* BasicCellDemoView.swift in Sources */, 441FE43E209A254900B04EF1 /* MarketsGridViewDemoView.swift in Sources */, 44AEFC2522E722FC00D3C307 /* BasicCellVariationsDemoView.swift in Sources */, 4441F9EF22CCF72F00DCFD2F /* AddressViewDemoView.swift in Sources */, + 9B7D5A2B22E1A5AF001E4005 /* KlimabroletDemoViewController.swift in Sources */, CF7C460E22257AE1001FB92C /* EarthHourDefaultData.swift in Sources */, 082D80D321C1440D00831BDE /* EmptyChristmasViewDemoView.swift in Sources */, 45D7C57120494F77000E788F /* SwitchViewDemoView.swift in Sources */, @@ -3416,6 +3466,7 @@ CFCDDA5F22731D60005E1F4A /* CalloutDemoView.swift in Sources */, 44A149F12137805C0053D5F7 /* SavedSearchesListViewDemoView.swift in Sources */, CFF9727321C3BA2200C85238 /* BannerTransparencyDemoView.swift in Sources */, + 9B7D5A2D22E1B3B4001E4005 /* KlimabroletEventsDemoViewController.swift in Sources */, DA4AD4D52105CFB00000F39E /* RadioButtonDemoView.swift in Sources */, 4443F9B1209D5ECE00E35719 /* Helpers.swift in Sources */, CF87A85A229C0C6600DA8243 /* ContactFormDemoView.swift in Sources */, @@ -3430,7 +3481,6 @@ DAD0D48E210731C60091DD4D /* AdReporterDemoView.swift in Sources */, 44A0F0B222E20FBF00BCCF4C /* TestCheck.swift in Sources */, DA93EFAA21C2BB2900207239 /* NewYearsDemoView.swift in Sources */, - 9A37DACD70E4383536D5312B /* FeedbackDemoView.swift in Sources */, 9F21365157F385AC63928150 /* FullscreenGalleryDemoViewController.swift in Sources */, DAE738C722C4C85E001C69E3 /* CarouselViewDemo.swift in Sources */, 9A37DDB3353F56739B23D22B /* FavoriteAdCellDemoView.swift in Sources */, @@ -3473,6 +3523,7 @@ CF87A857229C0C5700DA8243 /* ContactFormView.swift in Sources */, 441FE432209A24E500B04EF1 /* AdsGridViewLayoutConfiguration.swift in Sources */, 431875C1211180F100D71723 /* ReviewProfileCell.swift in Sources */, + 9BBC8AE122DF50E5003453B6 /* KlimabroletView.swift in Sources */, F26852FC2201DAD8000978C8 /* UserAdsListViewSeeAllAdsCell.swift in Sources */, 082D80CB21C13C7B00831BDE /* RoundedRectangleGiftView.swift in Sources */, 443A6420209A5044006BFB38 /* NotificationsListFooterView.swift in Sources */, @@ -3488,6 +3539,7 @@ 4441F9F922CF81F700DCFD2F /* AddressCardView.swift in Sources */, CFF9727521C3E92700C85238 /* BannerTransparencyViewModel.swift in Sources */, 45EDD62A20A1CCDF008F4503 /* ConsentTransparencyInfoView.swift in Sources */, + 9BCDFC7422E09DF700A80D7F /* KlimabroletActionsView.swift in Sources */, DAA9A3A9210215400021F7DC /* SelectionboxItem.swift in Sources */, 44A5579F22E71FEB001667AE /* BasicTableViewCell.swift in Sources */, F22612DC225C788A00472D22 /* StatisticsItemEmptyViewModel.swift in Sources */, @@ -3550,6 +3602,7 @@ 44F8831220551D59003E3171 /* NSAttributedStringExtensions.swift in Sources */, F22612D822572D9400472D22 /* StatisticsItemEmptyView.swift in Sources */, 44A149EB21377C7B0053D5F7 /* SavedSearchesListViewCell.swift in Sources */, + 9BCDFC7622E09E3C00A80D7F /* KlimabroletViewModel.swift in Sources */, CF136ACF220327F500247B30 /* InfoboxViewModel.swift in Sources */, 0881431F22D8718A008CB5DA /* FavoriteFoldersEmptyView.swift in Sources */, CBD2F08D20615990002AA385 /* TextField+State.swift in Sources */, @@ -3557,6 +3610,7 @@ 14EBA258215A633800613E5A /* LoadingView.swift in Sources */, 9B23769122DC6CEF00FCA381 /* NSLayoutAnchorExtensions.swift in Sources */, 44A557AE22E7211E001667AE /* RemoteImageTableViewCell.swift in Sources */, + 9B239E1122E093E800A4E9D0 /* KlimabroletContentView.swift in Sources */, 441D699C1FEA947600CD919A /* LayoutHelpers.swift in Sources */, DAB7FAAA21B690DD00BF8CC6 /* BottomSheetGestureController.swift in Sources */, DAB7FAAE21B6924E00BF8CC6 /* SpringAnimator.swift in Sources */, diff --git a/SnapshotTests/ReferenceImages_64/UnitTests.ComponentViewTests/testKlimabroletView@3x.png b/SnapshotTests/ReferenceImages_64/UnitTests.ComponentViewTests/testKlimabroletView@3x.png new file mode 100644 index 0000000000..e53ff649be Binary files /dev/null and b/SnapshotTests/ReferenceImages_64/UnitTests.ComponentViewTests/testKlimabroletView@3x.png differ diff --git a/Sources/Components/EarthHour/Views/EarthHourTagView.swift b/Sources/Components/EarthHour/Views/EarthHourTagView.swift index f1338950a1..1992793832 100644 --- a/Sources/Components/EarthHour/Views/EarthHourTagView.swift +++ b/Sources/Components/EarthHour/Views/EarthHourTagView.swift @@ -18,7 +18,7 @@ final class EarthHourTagView: UIView { return imageView }() - private lazy var stackView: UIStackView = { + private(set) lazy var stackView: UIStackView = { let stackView = UIStackView(withAutoLayout: true) stackView.axis = .horizontal stackView.spacing = .smallSpacing diff --git a/Sources/Components/Klimabrolet/KlimabroletView.swift b/Sources/Components/Klimabrolet/KlimabroletView.swift new file mode 100644 index 0000000000..a4d3d3a945 --- /dev/null +++ b/Sources/Components/Klimabrolet/KlimabroletView.swift @@ -0,0 +1,174 @@ +// +// Copyright © 2019 FINN AS. All rights reserved. +// + +import UIKit + +public protocol KlimabroletViewDelegate: AnyObject { + func klimabroletViewDidSelectReadMore(_ view: KlimabroletView) + func klimabroletViewDidSelectAccept(_ view: KlimabroletView) + func klimabroletViewDidSelectDecline(_ view: KlimabroletView) + func klimabroletViewDidSelectClose(_ view: KlimabroletView) +} + +public class KlimabroletView: UIView { + // MARK: - Public properties + + public weak var delegate: KlimabroletViewDelegate? + + // MARK: - Private properties + + private var shadowAnimationDuration = 0.12 + private var contentSizeObservation: NSKeyValueObservation? + + private lazy var closeButton: UIButton = { + let button = UIButton(withAutoLayout: true) + button.tintColor = .milk + button.setImage(UIImage(named: .cross), for: .normal) + button.backgroundColor = UIColor.black.withAlphaComponent(0.6) + button.contentEdgeInsets = UIEdgeInsets(all: 6) + button.addTarget(self, action: #selector(handleTapOnCloseButton), for: .touchUpInside) + + return button + }() + + private lazy var scrollView: UIScrollView = { + let scrollView = UIScrollView(withAutoLayout: true) + scrollView.bounces = true + scrollView.contentInset = UIEdgeInsets(bottom: .largeSpacing) + scrollView.delegate = self + scrollView.delaysContentTouches = false + return scrollView + }() + + private lazy var contentView: KlimabroletContentView = { + let view = KlimabroletContentView(withAutoLayout: true) + view.delegate = self + return view + }() + + private lazy var actionsView: KlimabroletActionsView = { + let view = KlimabroletActionsView(withAutoLayout: true) + view.layer.shadowOffset = .zero + view.delegate = self + return view + }() + + // MARK: - Initializers + + public override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() + } + + public override func layoutSubviews() { + super.layoutSubviews() + closeButton.layer.cornerRadius = closeButton.bounds.width / 2.0 + } + + // MARK: - Public methods + + public func configure(with viewModel: KlimabroletViewModel) { + contentView.configure(with: viewModel) + actionsView.configure( + primaryButtonTitle: viewModel.acceptButtonTitle, + secondaryButtonTitle: viewModel.declineButtonTitle + ) + } + + // MARK: - Private methods + + private func setup() { + backgroundColor = .milk + layer.cornerRadius = 20 + clipsToBounds = true + + scrollView.addSubview(contentView) + + contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true + contentView.fillInSuperview() + + addSubview(scrollView) + addSubview(actionsView) + addSubview(closeButton) + + NSLayoutConstraint.activate([ + closeButton.topAnchor.constraint(equalTo: topAnchor, constant: .mediumSpacing), + closeButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -.mediumSpacing), + + scrollView.topAnchor.constraint(equalTo: topAnchor), + scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), + scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), + scrollView.bottomAnchor.constraint(equalTo: actionsView.topAnchor), + + actionsView.leadingAnchor.constraint(equalTo: leadingAnchor), + actionsView.trailingAnchor.constraint(equalTo: trailingAnchor), + actionsView.bottomAnchor.constraint(equalTo: bottomAnchor) + ]) + + contentSizeObservation = scrollView.observe( + \UIScrollView.contentSize, options: [.old, .new], changeHandler: contentSizeDidChange(_:change:) + ) + } + + @objc private func handleTapOnCloseButton() { + delegate?.klimabroletViewDidSelectClose(self) + } + + private func contentSizeDidChange(_ scrollView: UIScrollView, change: NSKeyValueObservedChange) { + guard let contentSize = change.newValue else { + return + } + + if scrollView.contentOffset.y + scrollView.frame.height < contentSize.height { + actionsView.layer.shadowOpacity = 0.2 + } + } +} + +// MARK: - UIScrollViewDelegate + +extension KlimabroletView: UIScrollViewDelegate { + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + if scrollView.contentOffset.y + scrollView.frame.height < contentView.intrinsicContentSize.height { + animateShadow(fromValue: 0.2, toValue: 0, duration: shadowAnimationDuration) + } else { + animateShadow(fromValue: 0, toValue: 0.2, duration: shadowAnimationDuration) + } + } + + func animateShadow(fromValue from: Float, toValue to: Float, duration: Double) { + guard actionsView.layer.shadowOpacity != to else { return } + let animation = CABasicAnimation(keyPath: "shadowOpacity") + animation.fromValue = from + animation.toValue = to + animation.duration = duration + actionsView.layer.add(animation, forKey: nil) + actionsView.layer.shadowOpacity = to + } +} + +// MARK: - KlimabroletActionsViewDelegate + +extension KlimabroletView: KlimabroletActionsViewDelegate { + func klimabroletViewDidSelectPrimaryButton(_ view: KlimabroletActionsView) { + delegate?.klimabroletViewDidSelectAccept(self) + } + + func klimabroletViewDidSelectSecondaryButton(_ view: KlimabroletActionsView) { + delegate?.klimabroletViewDidSelectDecline(self) + } +} + +// MARK: - KlimabroletContentViewDelegate + +extension KlimabroletView: KlimabroletContentViewDelegate { + func klimabroletViewDidSelectReadMore(_ view: KlimabroletContentView) { + delegate?.klimabroletViewDidSelectReadMore(self) + } +} diff --git a/Sources/Components/Klimabrolet/KlimabroletViewModel.swift b/Sources/Components/Klimabrolet/KlimabroletViewModel.swift new file mode 100644 index 0000000000..8ca3ccd282 --- /dev/null +++ b/Sources/Components/Klimabrolet/KlimabroletViewModel.swift @@ -0,0 +1,14 @@ +// +// Copyright © 2019 FINN AS. All rights reserved. +// + +import Foundation + +public protocol KlimabroletViewModel { + var title: String { get } + var subtitle: String { get } + var bodyText: String { get } + var readMoreButtonTitle: String { get } + var acceptButtonTitle: String { get } + var declineButtonTitle: String { get } +} diff --git a/Sources/Components/Klimabrolet/Views/KlimabroletActionsView.swift b/Sources/Components/Klimabrolet/Views/KlimabroletActionsView.swift new file mode 100644 index 0000000000..9df81c8eb9 --- /dev/null +++ b/Sources/Components/Klimabrolet/Views/KlimabroletActionsView.swift @@ -0,0 +1,77 @@ +// +// Copyright © 2019 FINN AS. All rights reserved. +// + +import Foundation + +protocol KlimabroletActionsViewDelegate: AnyObject { + func klimabroletViewDidSelectPrimaryButton(_ view: KlimabroletActionsView) + func klimabroletViewDidSelectSecondaryButton(_ view: KlimabroletActionsView) +} + +class KlimabroletActionsView: UIView { + weak var delegate: KlimabroletActionsViewDelegate? + + // MARK: - Private subviews + + private lazy var primaryButton: UIButton = { + let button = Button(style: .callToAction) + button.translatesAutoresizingMaskIntoConstraints = false + button.titleLabel?.numberOfLines = 0 + button.addTarget(self, action: #selector(handleTapOnPrimaryButton), for: .touchUpInside) + return button + }() + + private lazy var secondaryButton: UIButton = { + let button = Button(style: .flat) + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(handleTapOnSecondaryButton), for: .touchUpInside) + return button + }() + + // MARK: - Initializers + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Internal methods + + func configure(primaryButtonTitle: String, secondaryButtonTitle: String) { + primaryButton.setTitle(primaryButtonTitle, for: .normal) + secondaryButton.setTitle(secondaryButtonTitle, for: .normal) + } + + // MARK: - Private methods + + private func setup() { + backgroundColor = .milk + + addSubview(primaryButton) + addSubview(secondaryButton) + + NSLayoutConstraint.activate([ + primaryButton.topAnchor.constraint(equalTo: topAnchor, constant: .mediumSpacing), + primaryButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: .mediumLargeSpacing), + primaryButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -.mediumLargeSpacing), + + secondaryButton.topAnchor.constraint(equalTo: primaryButton.bottomAnchor), + secondaryButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: .mediumLargeSpacing), + secondaryButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -.mediumLargeSpacing), + secondaryButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -.mediumLargeSpacing), + ]) + } + + @objc private func handleTapOnPrimaryButton() { + delegate?.klimabroletViewDidSelectPrimaryButton(self) + } + + @objc private func handleTapOnSecondaryButton() { + delegate?.klimabroletViewDidSelectSecondaryButton(self) + } +} diff --git a/Sources/Components/Klimabrolet/Views/KlimabroletContentView.swift b/Sources/Components/Klimabrolet/Views/KlimabroletContentView.swift new file mode 100644 index 0000000000..5b302383f8 --- /dev/null +++ b/Sources/Components/Klimabrolet/Views/KlimabroletContentView.swift @@ -0,0 +1,111 @@ +// +// Copyright © 2019 FINN AS. All rights reserved. +// + +import UIKit + +protocol KlimabroletContentViewDelegate: AnyObject { + func klimabroletViewDidSelectReadMore(_ view: KlimabroletContentView) +} + +class KlimabroletContentView: UIView { + weak var delegate: KlimabroletContentViewDelegate? + + private lazy var bannerImageView: UIView = { + let imageView = UIImageView(withAutoLayout: true) + imageView.image = UIImage(named: .klimaboletBanner) + return imageView + }() + + private lazy var subtitleTagView: EarthHourTagView = { + let view = EarthHourTagView(withAutoLayout: true) + view.stackView.alignment = .center + return view + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel(withAutoLayout: true) + let font = UIFont(name: FontType.bold.rawValue, size: 22)? + .scaledFont(forTextStyle: .title2) + label.font = font + label.textAlignment = .center + label.textColor = .licorice + label.numberOfLines = 0 + return label + }() + + private lazy var bodyTextLabel: UILabel = { + let label = Label(style: .body) + label.translatesAutoresizingMaskIntoConstraints = false + label.numberOfLines = 0 + label.textAlignment = .center + return label + }() + + private lazy var accessoryButton: UIButton = { + let button = Button(style: .link, size: .small) + button.translatesAutoresizingMaskIntoConstraints = false + button.titleLabel?.numberOfLines = 0 + button.addTarget(self, action: #selector(handleTapOnAccessoryButton), for: .touchUpInside) + return button + }() + + // MARK: - Init + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Internal methods + + func configure(with viewModel: KlimabroletViewModel) { + titleLabel.text = viewModel.title + subtitleTagView.titleLabel.text = viewModel.subtitle + bodyTextLabel.text = viewModel.bodyText + accessoryButton.setTitle(viewModel.readMoreButtonTitle, for: .normal) + } + + // MARK: - Private methods + + private func setup() { + backgroundColor = .milk + + addSubview(bannerImageView) + addSubview(titleLabel) + addSubview(subtitleTagView) + addSubview(bodyTextLabel) + addSubview(accessoryButton) + + NSLayoutConstraint.activate([ + bannerImageView.topAnchor.constraint(equalTo: topAnchor), + bannerImageView.leadingAnchor.constraint(equalTo: leadingAnchor), + bannerImageView.trailingAnchor.constraint(equalTo: trailingAnchor), + + titleLabel.topAnchor.constraint(equalTo: bannerImageView.bottomAnchor, constant: .mediumLargeSpacing), + titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: .mediumLargeSpacing), + titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -.mediumLargeSpacing), + + subtitleTagView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: .smallSpacing), + subtitleTagView.centerXAnchor.constraint(equalTo: centerXAnchor), + + bodyTextLabel.topAnchor.constraint(equalTo: subtitleTagView.bottomAnchor, constant: .mediumLargeSpacing), + bodyTextLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: .largeSpacing), + bodyTextLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -.largeSpacing), + + accessoryButton.topAnchor.constraint(equalTo: bodyTextLabel.bottomAnchor, constant: .mediumLargeSpacing), + accessoryButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: .mediumSpacing), + accessoryButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -.mediumSpacing), + accessoryButton.heightAnchor.constraint(greaterThanOrEqualToConstant: .largeSpacing), + accessoryButton.bottomAnchor.constraint(equalTo: bottomAnchor), + ]) + } + + @objc private func handleTapOnAccessoryButton() { + delegate?.klimabroletViewDidSelectReadMore(self) + } +} diff --git a/Sources/Resources/Assets.xcassets/Klimabrolet/Contents.json b/Sources/Resources/Assets.xcassets/Klimabrolet/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/Sources/Resources/Assets.xcassets/Klimabrolet/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sources/Resources/Assets.xcassets/Klimabrolet/cross.imageset/Contents.json b/Sources/Resources/Assets.xcassets/Klimabrolet/cross.imageset/Contents.json new file mode 100644 index 0000000000..7724f7fc66 --- /dev/null +++ b/Sources/Resources/Assets.xcassets/Klimabrolet/cross.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "cross.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/Sources/Resources/Assets.xcassets/Klimabrolet/cross.imageset/cross.pdf b/Sources/Resources/Assets.xcassets/Klimabrolet/cross.imageset/cross.pdf new file mode 100644 index 0000000000..ceb23bb860 Binary files /dev/null and b/Sources/Resources/Assets.xcassets/Klimabrolet/cross.imageset/cross.pdf differ diff --git a/Sources/Resources/Assets.xcassets/Klimabrolet/klimaboletBanner.imageset/Contents.json b/Sources/Resources/Assets.xcassets/Klimabrolet/klimaboletBanner.imageset/Contents.json new file mode 100644 index 0000000000..465207f8ad --- /dev/null +++ b/Sources/Resources/Assets.xcassets/Klimabrolet/klimaboletBanner.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "klimaboletBanner.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sources/Resources/Assets.xcassets/Klimabrolet/klimaboletBanner.imageset/klimaboletBanner.pdf b/Sources/Resources/Assets.xcassets/Klimabrolet/klimaboletBanner.imageset/klimaboletBanner.pdf new file mode 100644 index 0000000000..2241a2717a Binary files /dev/null and b/Sources/Resources/Assets.xcassets/Klimabrolet/klimaboletBanner.imageset/klimaboletBanner.pdf differ diff --git a/Sources/Resources/FinniversImageAsset.h b/Sources/Resources/FinniversImageAsset.h index c272563ed3..6e77858949 100644 --- a/Sources/Resources/FinniversImageAsset.h +++ b/Sources/Resources/FinniversImageAsset.h @@ -28,6 +28,7 @@ extern NSString *const FinniversImageAssetcheckCircle; extern NSString *const FinniversImageAssetcheckmarkBig; extern NSString *const FinniversImageAssetclassifieds; extern NSString *const FinniversImageAssetclose; +extern NSString *const FinniversImageAssetcross; extern NSString *const FinniversImageAssetdistance; extern NSString *const FinniversImageAssetdownload; extern NSString *const FinniversImageAssetearthHourClock; @@ -63,6 +64,7 @@ extern NSString *const FinniversImageAsseticonRealestatePrice; extern NSString *const FinniversImageAssetimportant; extern NSString *const FinniversImageAssetinfo; extern NSString *const FinniversImageAssetjobs; +extern NSString *const FinniversImageAssetklimaboletBanner; extern NSString *const FinniversImageAssetlistView; extern NSString *const FinniversImageAssetmagnifyingGlass; extern NSString *const FinniversImageAssetmapDirections; diff --git a/Sources/Resources/FinniversImageAsset.m b/Sources/Resources/FinniversImageAsset.m index 71715d9e68..d21bb37f15 100644 --- a/Sources/Resources/FinniversImageAsset.m +++ b/Sources/Resources/FinniversImageAsset.m @@ -28,6 +28,7 @@ NSString *const FinniversImageAssetcheckmarkBig = @"checkmarkBig"; NSString *const FinniversImageAssetclassifieds = @"classifieds"; NSString *const FinniversImageAssetclose = @"close"; +NSString *const FinniversImageAssetcross = @"cross"; NSString *const FinniversImageAssetdistance = @"distance"; NSString *const FinniversImageAssetdownload = @"download"; NSString *const FinniversImageAssetearthHourClock = @"earthHourClock"; @@ -63,6 +64,7 @@ NSString *const FinniversImageAssetimportant = @"important"; NSString *const FinniversImageAssetinfo = @"info"; NSString *const FinniversImageAssetjobs = @"jobs"; +NSString *const FinniversImageAssetklimaboletBanner = @"klimaboletBanner"; NSString *const FinniversImageAssetlistView = @"listView"; NSString *const FinniversImageAssetmagnifyingGlass = @"magnifyingGlass"; NSString *const FinniversImageAssetmapDirections = @"mapDirections"; @@ -151,6 +153,7 @@ @implementation UIImage (FinniversKit) FinniversImageAssetcheckmarkBig, FinniversImageAssetclassifieds, FinniversImageAssetclose, + FinniversImageAssetcross, FinniversImageAssetdistance, FinniversImageAssetdownload, FinniversImageAssetearthHourClock, @@ -186,6 +189,7 @@ @implementation UIImage (FinniversKit) FinniversImageAssetimportant, FinniversImageAssetinfo, FinniversImageAssetjobs, + FinniversImageAssetklimaboletBanner, FinniversImageAssetlistView, FinniversImageAssetmagnifyingGlass, FinniversImageAssetmapDirections, diff --git a/Sources/Resources/FinniversImageAsset.swift b/Sources/Resources/FinniversImageAsset.swift index b5061fa31e..35d7107817 100644 --- a/Sources/Resources/FinniversImageAsset.swift +++ b/Sources/Resources/FinniversImageAsset.swift @@ -39,6 +39,7 @@ public enum FinniversImageAsset: String { case checkmarkBig case classifieds case close + case cross case distance case download case earthHourClock @@ -74,6 +75,7 @@ public enum FinniversImageAsset: String { case important case info case jobs + case klimaboletBanner case listView case magnifyingGlass case mapDirections @@ -161,6 +163,7 @@ public enum FinniversImageAsset: String { .checkmarkBig, .classifieds, .close, + .cross, .distance, .download, .earthHourClock, @@ -196,6 +199,7 @@ public enum FinniversImageAsset: String { .important, .info, .jobs, + .klimaboletBanner, .listView, .magnifyingGlass, .mapDirections, diff --git a/UnitTests/ComponentViewTests.swift b/UnitTests/ComponentViewTests.swift index e769ab9745..dff2336add 100644 --- a/UnitTests/ComponentViewTests.swift +++ b/UnitTests/ComponentViewTests.swift @@ -170,4 +170,8 @@ class ComponentViewTests: FBSnapshotTestCase { func testTweakable() { snapshot(.tweakable) } + + func testKlimabroletView() { + snapshot(.klimabrolet) + } }