├── .gitignore
├── LICENSE
├── airbnb-datepicker
├── airbnb-datepicker.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── airbnb-datepicker
│ ├── AirbnbDatePicker.swift
│ ├── AirbnbDatePickerCell.swift
│ ├── AirbnbDatePickerFlowLayout.swift
│ ├── AirbnbDatePickerFooter.swift
│ ├── AirbnbDatePickerHeader.swift
│ ├── AirbnbDatePickerMonthHeader.swift
│ ├── AirbnbDatePickerViewController.swift
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Calendar.imageset
│ │ ├── Calendar-100.png
│ │ └── Contents.json
│ ├── Contents.json
│ └── Delete.imageset
│ │ ├── Contents.json
│ │ └── Delete-75 (1).png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── BaseCell.swift
│ ├── Date.swift
│ ├── Info.plist
│ ├── Theme.swift
│ ├── UIColor.swift
│ ├── Utility.swift
│ └── ViewController.swift
├── airbnb-main
├── airbnb-main.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── airbnb-main
│ ├── AirbnbButton.swift
│ ├── AirbnbCategoryTableCell.swift
│ ├── AirbnbContentCategory.swift
│ ├── AirbnbContentThumbnail.swift
│ ├── AirbnbExploreController.swift
│ ├── AirbnbExploreFeedController.swift
│ ├── AirbnbExploreHeaderView.swift
│ ├── AirbnbExploreHomeController.swift
│ ├── AirbnbHome.swift
│ ├── AirbnbHomeDetailController.swift
│ ├── AirbnbHomeItemCell.swift
│ ├── AirbnbHomeItemTableCell.swift
│ ├── AirbnbIconLabel.swift
│ ├── AirbnbMainController.swift
│ ├── AirbnbMapController.swift
│ ├── AirbnbMapItemCell.swift
│ ├── AirbnbPageTabItem.swift
│ ├── AirbnbPageTabNavigationView.swift
│ ├── AirbnbReview.swift
│ ├── AirbnbStar.swift
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Back.imageset
│ │ ├── Back-25.png
│ │ ├── Back-50.png
│ │ ├── Back-75.png
│ │ └── Contents.json
│ ├── Bed.imageset
│ │ ├── Bed-25.png
│ │ ├── Bed-50 (1).png
│ │ ├── Bed-75.png
│ │ └── Contents.json
│ ├── Collapse.imageset
│ │ ├── Collapse Arrow-25 (1).png
│ │ ├── Collapse Arrow-50 (1).png
│ │ ├── Collapse Arrow-75 (1).png
│ │ └── Contents.json
│ ├── Contents.json
│ ├── Door.imageset
│ │ ├── Contents.json
│ │ ├── Door Opened-25.png
│ │ ├── Door Opened-50.png
│ │ └── Door Opened-75.png
│ ├── Expand.imageset
│ │ ├── Contents.json
│ │ ├── Expand Arrow-25.png
│ │ ├── Expand Arrow-50 (1).png
│ │ └── Expand Arrow-75.png
│ ├── Globe.imageset
│ │ ├── Contents.json
│ │ ├── Globe Earth-25.png
│ │ ├── Globe Earth-50.png
│ │ └── Globe Earth-75.png
│ ├── Heart.imageset
│ │ ├── Contents.json
│ │ ├── Hearts-25.png
│ │ ├── Hearts-50 (1).png
│ │ └── Hearts-75.png
│ ├── Message.imageset
│ │ ├── Contents.json
│ │ ├── Message-25.png
│ │ ├── Message-50.png
│ │ └── Message-75.png
│ ├── Profile.imageset
│ │ ├── Contents.json
│ │ ├── User-25.png
│ │ ├── User-50.png
│ │ └── User-75.png
│ ├── Search.imageset
│ │ ├── Contents.json
│ │ ├── Search-25.png
│ │ ├── Search-50.png
│ │ └── Search-75.png
│ ├── Shower.imageset
│ │ ├── Contents.json
│ │ ├── Shower and Tub-25.png
│ │ ├── Shower and Tub-50.png
│ │ └── Shower and Tub-75.png
│ ├── Star Empty.imageset
│ │ ├── Contents.json
│ │ ├── Star-25.png
│ │ ├── Star-50.png
│ │ └── Star-75.png
│ ├── Star Filled.imageset
│ │ ├── Contents.json
│ │ ├── Star Filled-25.png
│ │ ├── Star Filled-50.png
│ │ └── Star Filled-75.png
│ ├── Star Half Empty.imageset
│ │ ├── Contents.json
│ │ ├── Star Half Empty-25.png
│ │ ├── Star Half Empty-50.png
│ │ └── Star Half Empty-75.png
│ ├── Upload.imageset
│ │ ├── Contents.json
│ │ ├── Upload-25.png
│ │ ├── Upload-50.png
│ │ └── Upload-75.png
│ ├── home-1.imageset
│ │ ├── Contents.json
│ │ └── home-1.jpeg
│ ├── home-10.imageset
│ │ ├── Contents.json
│ │ └── home-10.jpeg
│ ├── home-2.imageset
│ │ ├── Contents.json
│ │ └── home-2.jpeg
│ ├── home-3.imageset
│ │ ├── Contents.json
│ │ └── home-3.jpeg
│ ├── home-4.imageset
│ │ ├── Contents.json
│ │ └── home-4.jpeg
│ ├── home-5.imageset
│ │ ├── Contents.json
│ │ └── home-5.jpeg
│ ├── home-6.imageset
│ │ ├── Contents.json
│ │ └── home-6.jpeg
│ ├── home-7.imageset
│ │ ├── Contents.json
│ │ └── home-7.jpeg
│ ├── home-8.imageset
│ │ ├── Contents.json
│ │ └── home-8.jpeg
│ ├── home-9.imageset
│ │ ├── Contents.json
│ │ └── home-9.jpeg
│ └── profpic.imageset
│ │ ├── Contents.json
│ │ └── profpic.jpeg
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── BaseCollectionCell.swift
│ ├── BasePageTabItemView.swift
│ ├── BaseTableCell.swift
│ ├── BaseTableController.swift
│ ├── ImageExpandAnimationController.swift
│ ├── ImageShrinkAnimationController.swift
│ ├── Info.plist
│ ├── String.swift
│ ├── Theme.swift
│ ├── UIColor.swift
│ ├── UIImage.swift
│ ├── UITabBar.swift
│ └── VerticalAlignLabel.swift
├── airbnb-occupant-filter
├── airbnb-occupant-filter.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
└── airbnb-occupant-filter
│ ├── AirbnbCounter.swift
│ ├── AirbnbOccupantFilter.swift
│ ├── AirbnbOccupantFilterController.swift
│ ├── AirbnbSwitch.swift
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Checkmark.imageset
│ │ ├── Checkmark-25.png
│ │ ├── Checkmark-50.png
│ │ ├── Checkmark-75.png
│ │ └── Contents.json
│ ├── Contents.json
│ ├── Delete.imageset
│ │ ├── Contents.json
│ │ ├── Delete-25.png
│ │ ├── Delete-50.png
│ │ └── Delete-75.png
│ ├── Family.imageset
│ │ ├── Contents.json
│ │ ├── Family Man Woman-25.png
│ │ ├── Family Man Woman-50.png
│ │ └── Family Man Woman-75.png
│ ├── Minus.imageset
│ │ ├── Contents.json
│ │ ├── Minus-25.png
│ │ ├── Minus-48.png
│ │ └── Minus-75.png
│ └── Plus.imageset
│ │ ├── Contents.json
│ │ ├── Plus Math-25.png
│ │ ├── Plus Math-48.png
│ │ └── Plus Math-75.png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── Theme.swift
│ ├── UIColor.swift
│ ├── UIImage.swift
│ └── ViewController.swift
├── frameworks
├── airbnb-datepicker
│ ├── airbnb-datepicker.xcodeproj
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ └── airbnb-datepicker
│ │ ├── AirbnbDatePicker.swift
│ │ ├── AirbnbDatePickerCell.swift
│ │ ├── AirbnbDatePickerFlowLayout.swift
│ │ ├── AirbnbDatePickerFooter.swift
│ │ ├── AirbnbDatePickerHeader.swift
│ │ ├── AirbnbDatePickerMonthHeader.swift
│ │ ├── AirbnbDatePickerViewController.swift
│ │ ├── Assets.xcassets
│ │ ├── Calendar.imageset
│ │ │ ├── Calendar-25.png
│ │ │ ├── Calendar-50.png
│ │ │ ├── Calendar-75.png
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── Delete.imageset
│ │ │ ├── Contents.json
│ │ │ └── Delete-75 (1).png
│ │ ├── BaseCell.swift
│ │ ├── Date.swift
│ │ ├── Info.plist
│ │ ├── Theme.swift
│ │ ├── UIColor.swift
│ │ ├── Utility.swift
│ │ └── airbnb-datepicker.h
└── airbnb-occupant-filter
│ ├── airbnb-occupant-filter.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── airbnb-occupant-filter
│ ├── AirbnbCounter.swift
│ ├── AirbnbOccupantFilter.swift
│ ├── AirbnbOccupantFilterController.swift
│ ├── AirbnbSwitch.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Checkmark.imageset
│ │ ├── Checkmark-25.png
│ │ ├── Checkmark-50.png
│ │ ├── Checkmark-75.png
│ │ └── Contents.json
│ ├── Contents.json
│ ├── Delete.imageset
│ │ ├── Contents.json
│ │ ├── Delete-25.png
│ │ ├── Delete-50.png
│ │ └── Delete-75.png
│ ├── Family.imageset
│ │ ├── Contents.json
│ │ ├── Family Man Woman-25.png
│ │ ├── Family Man Woman-50.png
│ │ └── Family Man Woman-75.png
│ ├── Minus.imageset
│ │ ├── Contents.json
│ │ ├── Minus-25.png
│ │ ├── Minus-48.png
│ │ └── Minus-75.png
│ └── Plus.imageset
│ │ ├── Contents.json
│ │ ├── Plus Math-25.png
│ │ ├── Plus Math-48.png
│ │ └── Plus Math-75.png
│ ├── Info.plist
│ ├── Theme.swift
│ ├── UIColor.swift
│ ├── UIImage.swift
│ └── airbnb-occupant-filter.h
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | # Pods/
47 |
48 | # Carthage
49 | #
50 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
51 | # Carthage/Checkouts
52 |
53 | Carthage/Build
54 |
55 | # fastlane
56 | #
57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58 | # screenshots whenever they are needed.
59 | # For more information about the recommended setup visit:
60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
61 |
62 | fastlane/report.xml
63 | fastlane/Preview.html
64 | fastlane/screenshots
65 | fastlane/test_output
66 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 yonasstephen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/AirbnbDatePicker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePicker.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 22/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class AirbnbDatePicker: UIView, AirbnbDatePickerDelegate {
12 |
13 | public var selectedStartDate: Date?
14 | public var selectedEndDate: Date?
15 | public var delegate: UIViewController?
16 |
17 | var dateFormatter: DateFormatter {
18 | get {
19 | let f = DateFormatter()
20 | f.dateFormat = "d MMM"
21 | return f
22 | }
23 | }
24 |
25 | public override init(frame: CGRect) {
26 | super.init(frame: frame)
27 | setupViews()
28 | }
29 |
30 | public required init?(coder aDecoder: NSCoder) {
31 | fatalError("init(coder:) has not been implemented")
32 | }
33 |
34 | public lazy var dateInputButton: UIButton = {
35 | let btn = UIButton()
36 | btn.translatesAutoresizingMaskIntoConstraints = false
37 | btn.backgroundColor = Theme.PRIMARY_COLOR
38 | btn.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left
39 | btn.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
40 | btn.adjustsImageWhenHighlighted = false
41 | btn.addTarget(self, action: #selector(AirbnbDatePicker.showDatePicker), for: .touchUpInside)
42 |
43 | let img = UIImage(named: "Calendar", in: Bundle(for: AirbnbDatePicker.self), compatibleWith: nil)
44 | btn.setImage(img, for: .normal)
45 | btn.imageView?.contentMode = .scaleAspectFit
46 |
47 | btn.setTitle("Anytime", for: .normal)
48 | btn.setTitleColor(UIColor.white, for: .normal)
49 | btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 15)
50 | btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
51 | btn.titleLabel?.lineBreakMode = .byTruncatingTail
52 | return btn
53 | }()
54 |
55 | func setupViews() {
56 | addSubview(dateInputButton)
57 |
58 | dateInputButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
59 | dateInputButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
60 | dateInputButton.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
61 | dateInputButton.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
62 | }
63 |
64 | @objc func showDatePicker() {
65 | let datePickerViewController = AirbnbDatePickerViewController(dateFrom: selectedStartDate, dateTo: selectedEndDate)
66 | datePickerViewController.delegate = self
67 | let navigationController = UINavigationController(rootViewController: datePickerViewController)
68 | delegate?.present(navigationController, animated: true, completion: nil)
69 | }
70 |
71 | public func datePickerController(_ datePickerController: AirbnbDatePickerViewController, didSaveStartDate startDate: Date?, endDate: Date?) {
72 | selectedStartDate = startDate
73 | selectedEndDate = endDate
74 |
75 | if selectedStartDate == nil && selectedEndDate == nil {
76 | dateInputButton.setTitle("Anytime", for: .normal)
77 |
78 | } else {
79 | dateInputButton.setTitle("\(dateFormatter.string(from: startDate!)) - \(dateFormatter.string(from: endDate!))", for: .normal)
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/AirbnbDatePickerCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePickerCell.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 23/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbDatePickerCell: BaseCell {
12 |
13 | var type: AirbnbDatePickerCellType! = []
14 |
15 | var dateLabel: UILabel = {
16 | let label = UILabel()
17 | label.translatesAutoresizingMaskIntoConstraints = false
18 | label.textAlignment = .center
19 | label.font = UIFont.boldSystemFont(ofSize: 15)
20 | label.textColor = UIColor.white
21 | return label
22 | }()
23 |
24 | var highlightView: UIView = {
25 | let view = UIView()
26 | view.translatesAutoresizingMaskIntoConstraints = false
27 | view.backgroundColor = UIColor.clear
28 | return view
29 | }()
30 |
31 | override func setupViews() {
32 | super.setupViews()
33 |
34 | addSubview(dateLabel)
35 |
36 | dateLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
37 | dateLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
38 | dateLabel.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
39 | dateLabel.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
40 |
41 | addSubview(highlightView)
42 |
43 | highlightView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
44 | highlightView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
45 | highlightView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
46 | highlightView.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
47 | }
48 |
49 | func configureCell() {
50 | if type.contains(.Selected) || type.contains(.SelectedStartDate) || type.contains(.SelectedEndDate) || type.contains(.InBetweenDate) {
51 |
52 | dateLabel.layer.cornerRadius = 0
53 | dateLabel.layer.borderColor = UIColor.white.cgColor
54 | dateLabel.layer.borderWidth = 1
55 | dateLabel.layer.backgroundColor = UIColor.white.cgColor
56 | dateLabel.layer.mask = nil
57 | dateLabel.textColor = Theme.SECONDARY_COLOR
58 |
59 | if type.contains(.SelectedStartDate) {
60 | let side = frame.size.width / 2
61 | let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width: side, height: side))
62 | let shape = CAShapeLayer()
63 | shape.path = maskPath.cgPath
64 | dateLabel.layer.mask = shape
65 |
66 | } else if type.contains(.SelectedEndDate) {
67 | let side = frame.size.width / 2
68 | let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize(width: side, height: side))
69 | let shape = CAShapeLayer()
70 | shape.path = maskPath.cgPath
71 | dateLabel.layer.mask = shape
72 |
73 | } else if !type.contains(.InBetweenDate) {
74 | dateLabel.layer.cornerRadius = frame.size.width / 2
75 | }
76 |
77 | } else if type.contains(.PastDate) {
78 |
79 | dateLabel.layer.cornerRadius = 0
80 | dateLabel.layer.borderColor = UIColor.clear.cgColor
81 | dateLabel.layer.borderWidth = 0
82 | dateLabel.layer.backgroundColor = UIColor.clear.cgColor
83 | dateLabel.layer.mask = nil
84 | dateLabel.textColor = Theme.SECONDARY_COLOR
85 |
86 | } else if type.contains(.Today) {
87 |
88 | dateLabel.layer.cornerRadius = self.frame.size.width / 2
89 | dateLabel.layer.borderColor = Theme.SECONDARY_COLOR.cgColor
90 | dateLabel.layer.borderWidth = 1
91 | dateLabel.layer.backgroundColor = UIColor.clear.cgColor
92 | dateLabel.layer.mask = nil
93 | dateLabel.textColor = UIColor.white
94 |
95 | } else {
96 |
97 | dateLabel.layer.cornerRadius = 0
98 | dateLabel.layer.borderColor = UIColor.clear.cgColor
99 | dateLabel.layer.borderWidth = 0
100 | dateLabel.layer.backgroundColor = UIColor.clear.cgColor
101 | dateLabel.layer.mask = nil
102 | dateLabel.textColor = UIColor.white
103 |
104 | }
105 |
106 |
107 | if type.contains(.Highlighted) {
108 | highlightView.backgroundColor = UIColor(red: 200 / 255, green: 200 / 255, blue: 200 / 255, alpha: 0.6)
109 | highlightView.layer.cornerRadius = frame.size.width / 2
110 | } else {
111 | highlightView.backgroundColor = UIColor.clear
112 | }
113 | }
114 | }
115 |
116 | struct AirbnbDatePickerCellType: OptionSet {
117 | let rawValue: Int
118 |
119 | static let Date = AirbnbDatePickerCellType(rawValue: 1 << 0) // has number
120 | static let Empty = AirbnbDatePickerCellType(rawValue: 1 << 1) // has no number
121 | static let PastDate = AirbnbDatePickerCellType(rawValue: 1 << 2) // disabled
122 | static let Today = AirbnbDatePickerCellType(rawValue: 1 << 3) // has circle
123 | static let Selected = AirbnbDatePickerCellType(rawValue: 1 << 4) // has filled circle
124 | static let SelectedStartDate = AirbnbDatePickerCellType(rawValue: 1 << 5) // has half filled circle on the left
125 | static let SelectedEndDate = AirbnbDatePickerCellType(rawValue: 1 << 6) // has half filled circle on the right
126 | static let InBetweenDate = AirbnbDatePickerCellType(rawValue: 1 << 7) // has filled square
127 | static let Highlighted = AirbnbDatePickerCellType(rawValue: 1 << 8) // has
128 | }
129 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/AirbnbDatePickerFlowLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePickerFlowLayout.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 28/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbDatePickerFlowLayout : UICollectionViewFlowLayout {
12 |
13 | let cellSpacing:CGFloat = 0
14 |
15 | override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
16 | if let attributes = super.layoutAttributesForElements(in: rect) {
17 | for (index, attribute) in attributes.enumerated() {
18 | if index == 0 { continue }
19 | let prevLayoutAttributes = attributes[index - 1]
20 | let origin = prevLayoutAttributes.frame.maxX
21 | if origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize.width {
22 | attribute.frame.origin.x = origin + cellSpacing
23 | }
24 | }
25 | return attributes
26 | }
27 | return nil
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/AirbnbDatePickerFooter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePickerFooter.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 24/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol AirbnbDatePickerFooterDelegate {
12 | func didSave()
13 | }
14 |
15 | class AirbnbDatePickerFooter: UIView {
16 |
17 | var delegate: AirbnbDatePickerFooterDelegate?
18 | var isSaveEnabled: Bool? {
19 | didSet {
20 | if let enabled = isSaveEnabled, enabled {
21 | saveButton.isEnabled = true
22 | saveButton.alpha = 1
23 | } else {
24 | saveButton.isEnabled = false
25 | saveButton.alpha = 0.5
26 | }
27 | }
28 | }
29 |
30 | lazy var saveButton: UIButton = {
31 | let btn = UIButton()
32 | btn.translatesAutoresizingMaskIntoConstraints = false
33 | btn.backgroundColor = Theme.SECONDARY_COLOR
34 | btn.setTitleColor(UIColor.white, for: .normal)
35 | btn.setTitle("Save", for: .normal)
36 | btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
37 | btn.addTarget(self, action: #selector(AirbnbDatePickerFooter.handleSave), for: .touchUpInside)
38 | return btn
39 | }()
40 |
41 | override init(frame: CGRect) {
42 | super.init(frame: frame)
43 |
44 | self.backgroundColor = Theme.PRIMARY_COLOR
45 |
46 | addSubview(saveButton)
47 |
48 | saveButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
49 | saveButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
50 | saveButton.heightAnchor.constraint(equalTo: heightAnchor, constant: -20).isActive = true
51 | saveButton.widthAnchor.constraint(equalTo: widthAnchor, constant: -30).isActive = true
52 | }
53 |
54 | required init?(coder aDecoder: NSCoder) {
55 | fatalError("init(coder:) has not been implemented")
56 | }
57 |
58 | @objc func handleSave() {
59 | if let del = delegate {
60 | del.didSave()
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/AirbnbDatePickerMonthHeader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePickerMonthHeader.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 23/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbDatePickerMonthHeader: BaseCell {
12 |
13 | var monthLabel: UILabel = {
14 | let label = UILabel()
15 | label.translatesAutoresizingMaskIntoConstraints = false
16 | label.textColor = UIColor.white
17 | label.font = UIFont.systemFont(ofSize: 24)
18 | return label
19 | }()
20 |
21 | override func setupViews() {
22 | super.setupViews()
23 |
24 | addSubview(monthLabel)
25 |
26 | monthLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 20).isActive = true
27 | monthLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
28 | monthLabel.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
29 | monthLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 22/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Calendar-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Calendar-100.png
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "Calendar-100.png",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Delete.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "Delete-75 (1).png",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Delete.imageset/Delete-75 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Delete.imageset/Delete-75 (1).png
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/BaseCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseCell.swift
3 | // padstaview
4 | //
5 | // Created by Yonas Stephen on 11/10/16.
6 | // Copyright © 2016 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BaseCell: UICollectionViewCell {
12 | override init(frame: CGRect) {
13 | super.init(frame: frame)
14 | setupViews()
15 | }
16 |
17 | required init?(coder aDecoder: NSCoder) {
18 | fatalError("init(coder:) has not been implemented")
19 | }
20 |
21 | func setupViews() {
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Date.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Date.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 24/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Date {
12 | func startOfMonth() -> Date {
13 | return Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
14 | }
15 |
16 | func endOfMonth() -> Date {
17 | return Calendar.current.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth())!
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeRight
35 | UIInterfaceOrientationLandscapeLeft
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Theme.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Theme.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 23/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class Theme {
12 |
13 | static let PRIMARY_COLOR = UIColor(r: 0, g: 132, b: 137)
14 | static let SECONDARY_COLOR = UIColor(r: 65, g: 171, b: 175)
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/UIColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor.swift
3 | // mychurch-app
4 | //
5 | // Created by Yonas Stephen on 30/6/16.
6 | // Copyright © 2016 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | convenience init(hex: String) {
13 | var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
14 | if (cString.hasPrefix("#")) {
15 | cString = String(cString.suffix(from: cString.startIndex))
16 | }
17 |
18 | if ((cString.count) != 6) {
19 | self.init()
20 | } else {
21 | var rgbValue:UInt32 = 0
22 | Scanner(string: cString).scanHexInt32(&rgbValue)
23 |
24 | self.init(
25 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
26 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
27 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
28 | alpha: CGFloat(1.0)
29 | )
30 | }
31 | }
32 |
33 | convenience init(r: CGFloat, g: CGFloat, b: CGFloat) {
34 | self.init(red: CGFloat(r / 255), green: CGFloat(g / 255), blue: CGFloat(b / 255), alpha: CGFloat(1))
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/Utility.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Utility.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 2/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Utility {
12 |
13 | static var calendar: Calendar {
14 | get {
15 | var c = Calendar.current
16 | c.timeZone = TimeZone(abbreviation: "GMT")!
17 | return c
18 | }
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/airbnb-datepicker/airbnb-datepicker/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 22/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | lazy var datePicker: AirbnbDatePicker = {
14 | let btn = AirbnbDatePicker()
15 | btn.translatesAutoresizingMaskIntoConstraints = false
16 | btn.delegate = self
17 | return btn
18 | }()
19 |
20 | override func viewDidLoad() {
21 | super.viewDidLoad()
22 |
23 | view.addSubview(datePicker)
24 |
25 | datePicker.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
26 | datePicker.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
27 | datePicker.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
28 | datePicker.heightAnchor.constraint(equalToConstant: 50).isActive = true
29 |
30 | }
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbButton.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 13/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbButton: UIButton {
12 |
13 | override init(frame: CGRect) {
14 | super.init(frame: frame)
15 |
16 | backgroundColor = Theme.TERTIARY_COLOR
17 | setTitleColor(UIColor.white, for: .normal)
18 | layer.cornerRadius = 5
19 | }
20 |
21 | required init?(coder aDecoder: NSCoder) {
22 | fatalError("init(coder:) has not been implemented")
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbCategoryTableCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbCategoryCell.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 7/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol AirbnbCategoryTableCellDelegate {
12 | func categoryTableCell(_ tableCell: AirbnbCategoryTableCell, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
13 | }
14 |
15 | class AirbnbCategoryTableCell: BaseTableCell {
16 |
17 | let cellID = "cellID"
18 | var indexPath: IndexPath?
19 |
20 | var layoutSubviewFirstTime: Bool = true
21 | var delegate: AirbnbCategoryTableCellDelegate?
22 |
23 | var items: [AirbnbHome] = [AirbnbHome]() {
24 | didSet {
25 | collectionView.reloadData()
26 | }
27 | }
28 |
29 | var title: String? {
30 | didSet {
31 | titleLabel.text = title
32 | }
33 | }
34 |
35 | var titleLabel: UILabel = {
36 | let view = UILabel()
37 | view.translatesAutoresizingMaskIntoConstraints = false
38 | view.font = UIFont.boldSystemFont(ofSize: 16)
39 | return view
40 | }()
41 |
42 | lazy var collectionView: UICollectionView = {
43 | let layout = UICollectionViewFlowLayout()
44 | layout.scrollDirection = .horizontal
45 | layout.minimumInteritemSpacing = 0
46 | layout.minimumLineSpacing = 0
47 | layout.itemSize = CGSize(width: 280, height: 230)
48 |
49 | let view = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
50 | view.translatesAutoresizingMaskIntoConstraints = false
51 | view.backgroundColor = UIColor.white
52 | view.register(AirbnbHomeItemCell.self, forCellWithReuseIdentifier: self.cellID)
53 | view.showsHorizontalScrollIndicator = false
54 | view.dataSource = self
55 | view.delegate = self
56 | return view
57 | }()
58 |
59 | override func setupViews() {
60 | super.setupViews()
61 |
62 | addSubview(titleLabel)
63 |
64 | titleLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
65 | titleLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
66 | titleLabel.widthAnchor.constraint(equalTo: widthAnchor, constant: -30).isActive = true
67 | titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
68 |
69 | addSubview(collectionView)
70 |
71 | collectionView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
72 | collectionView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor).isActive = true
73 | collectionView.heightAnchor.constraint(equalToConstant: 250).isActive = true
74 | collectionView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
75 |
76 | }
77 |
78 | override func layoutSubviews() {
79 | super.layoutSubviews()
80 |
81 | if layoutSubviewFirstTime {
82 | layoutSubviewFirstTime = false
83 | }
84 | }
85 | }
86 |
87 | extension AirbnbCategoryTableCell: UICollectionViewDataSource {
88 | func numberOfSections(in collectionView: UICollectionView) -> Int {
89 | return 1
90 | }
91 |
92 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
93 | return items.count
94 | }
95 |
96 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
97 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! AirbnbHomeItemCell
98 |
99 | cell.home = items[indexPath.item]
100 |
101 | return cell
102 | }
103 | }
104 |
105 | extension AirbnbCategoryTableCell: UICollectionViewDelegate {
106 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
107 | if let del = delegate {
108 | del.categoryTableCell(self, collectionView: collectionView, didSelectItemAt: indexPath)
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbContentCategory.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbContentCategory.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 7/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbContentCategory {
12 |
13 | var categoryName: String?
14 | var contents: [AirbnbContentThumbnail]?
15 |
16 | init() {
17 |
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbContentThumbnail.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbContentThumbnail.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 7/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbContentThumbnail {
12 | var thumbail: UIImage?
13 | var price: Double?
14 | var description: String?
15 | var review: Int?
16 | var type: AirbnbContentThumbnailType?
17 |
18 | init() {
19 | }
20 | }
21 |
22 | enum AirbnbContentThumbnailType: Int {
23 | case Home = 0, Experience, Place
24 | }
25 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbExploreFeedController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbExploreFeedController.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 12/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbExploreFeedController: BaseTableController {
12 |
13 | let cellID = "cellID"
14 |
15 | var categories = ["Just Booked", "Homes", "Experiences", "Featured Destinations"]
16 | let locations = ["Milan", "London", "Stavanger", "Munich"]
17 | lazy var homes: [AirbnbHome] = {
18 | var arr = [AirbnbHome]()
19 | for i in 0..<4 {
20 | let location = self.locations[Int(arc4random_uniform(UInt32(self.locations.count)))]
21 | let home = AirbnbHome(imageName: "home-" + "\(i + 1)", description: "Entire home in \(location)", price: Int(arc4random_uniform(100) + 200), reviewCount: Int(arc4random_uniform(300) + 1), rating: Double(arc4random()) / Double(UINT32_MAX) + 4)
22 | arr.append(home)
23 | }
24 | return arr
25 | }()
26 |
27 | lazy var tableView: UITableView = {
28 | let view = UITableView()
29 | view.translatesAutoresizingMaskIntoConstraints = false
30 | view.dataSource = self
31 | view.delegate = self
32 | view.register(AirbnbCategoryTableCell.self, forCellReuseIdentifier: self.cellID)
33 | view.rowHeight = 300
34 | view.separatorStyle = .none
35 | view.showsVerticalScrollIndicator = false
36 | view.allowsSelection = false
37 | return view
38 | }()
39 |
40 | override func viewDidLoad() {
41 | super.viewDidLoad()
42 |
43 | setupTableView()
44 | }
45 |
46 | func setupTableView() {
47 | view.addSubview(tableView)
48 |
49 | tableView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
50 | tableView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
51 | tableView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
52 | tableView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
53 | }
54 | }
55 |
56 | extension AirbnbExploreFeedController: UITableViewDataSource {
57 |
58 | func numberOfSections(in tableView: UITableView) -> Int {
59 | return categories.count
60 | }
61 |
62 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
63 | return 1
64 | }
65 |
66 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
67 | let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! AirbnbCategoryTableCell
68 |
69 | cell.title = categories[indexPath.section]
70 | cell.items = homes
71 | cell.indexPath = indexPath // needed for dismiss animation
72 |
73 | if let parent = parent as? AirbnbCategoryTableCellDelegate {
74 | cell.delegate = parent
75 | }
76 |
77 | return cell
78 | }
79 | }
80 |
81 |
82 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbExploreHomeController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbExploreHomeController.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 23/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbExploreHomeController: BaseTableController {
12 |
13 | let cellID = "cellID"
14 |
15 | let locations = ["Oslo", "Stockholm", "Barcelona", "Madrid", "Copenhagen", "London", "Milan", "Rome", "Hamburg"]
16 |
17 | lazy var items: [AirbnbHome] = {
18 | var arr = [AirbnbHome]()
19 | for i in 5..<11 {
20 | let location = self.locations[Int(arc4random_uniform(UInt32(self.locations.count)))]
21 | let item = AirbnbHome(imageName: "home-\(i)", description: "Entire home in \(location)", price: Int(arc4random_uniform(100) + 200), reviewCount: Int(arc4random_uniform(300) + 1), rating: Double(arc4random()) / Double(UINT32_MAX) + 4)
22 | arr.append(item)
23 | }
24 | return arr
25 | }()
26 |
27 | lazy var tableView: UITableView = {
28 | let view = UITableView()
29 | view.translatesAutoresizingMaskIntoConstraints = false
30 | view.dataSource = self
31 | view.delegate = self
32 | view.register(AirbnbHomeItemTableCell.self, forCellReuseIdentifier: self.cellID)
33 | view.allowsSelection = false
34 | view.rowHeight = 15 + 250 + 20 + 20 + 15
35 | view.separatorStyle = .none
36 | return view
37 | }()
38 |
39 | override func viewDidLoad() {
40 | super.viewDidLoad()
41 |
42 | setupTableView()
43 | }
44 |
45 | func setupTableView() {
46 | view.addSubview(tableView)
47 |
48 | tableView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
49 | tableView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
50 | tableView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
51 | tableView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
52 | }
53 | }
54 |
55 | extension AirbnbExploreHomeController: UITableViewDataSource {
56 | func numberOfSections(in tableView: UITableView) -> Int {
57 | return 1
58 | }
59 |
60 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
61 | return items.count
62 | }
63 |
64 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
65 | let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! AirbnbHomeItemTableCell
66 |
67 | //cell.textLabel?.text = "\(indexPath.item)"
68 | cell.home = items[indexPath.row]
69 |
70 | return cell
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbHome.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbHome.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 3/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class AirbnbHome {
12 | var imageName: String
13 | var homeDescription: String
14 | var price: Int
15 | var rating: Double
16 | var reviewCount: Int
17 |
18 | init(imageName: String, description: String, price: Int, reviewCount: Int, rating: Double) {
19 | self.imageName = imageName
20 | self.homeDescription = description
21 | self.price = price
22 | self.reviewCount = reviewCount
23 | self.rating = rating
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbHomeItemCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbHomeItemCell.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 3/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbHomeItemCell: BaseCollectionCell {
12 |
13 | var home: AirbnbHome? {
14 | didSet {
15 | imageView.image = UIImage(named: home!.imageName)
16 | priceLabel.text = "$\(home!.price)"
17 | descriptionLabel.text = home?.homeDescription
18 | reviewCountLabel.text = "\(home!.reviewCount) Reviews"
19 | ratingView.rating = home!.rating
20 | }
21 | }
22 |
23 | var homeDescription: String? {
24 | didSet {
25 | descriptionLabel.text = homeDescription
26 | }
27 | }
28 |
29 | var imageView: UIImageView = {
30 | let view = UIImageView()
31 | view.translatesAutoresizingMaskIntoConstraints = false
32 | view.contentMode = .scaleAspectFill
33 | view.clipsToBounds = true
34 | return view
35 | }()
36 |
37 | var priceLabel: UILabel = {
38 | let view = UILabel()
39 | view.translatesAutoresizingMaskIntoConstraints = false
40 | view.font = UIFont.boldSystemFont(ofSize: 14)
41 | view.textColor = UIColor.black
42 | return view
43 | }()
44 |
45 | var descriptionLabel: UILabel = {
46 | let view = UILabel()
47 | view.translatesAutoresizingMaskIntoConstraints = false
48 | view.font = UIFont.systemFont(ofSize: 14)
49 | view.textColor = UIColor.gray
50 | return view
51 | }()
52 |
53 | var ratingView: AirbnbReview = {
54 | let view = AirbnbReview()
55 | view.translatesAutoresizingMaskIntoConstraints = false
56 | return view
57 | }()
58 |
59 | var reviewCountLabel: UILabel = {
60 | let view = UILabel()
61 | view.translatesAutoresizingMaskIntoConstraints = false
62 | view.font = UIFont.boldSystemFont(ofSize: 10)
63 | view.textColor = UIColor.darkGray
64 | return view
65 | }()
66 |
67 | override func setupViews() {
68 |
69 | addSubview(imageView)
70 |
71 | imageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
72 | imageView.heightAnchor.constraint(equalToConstant: 180).isActive = true
73 | imageView.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
74 | imageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
75 |
76 | addSubview(priceLabel)
77 |
78 | priceLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 10).isActive = true
79 | priceLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
80 | priceLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
81 | priceLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true
82 |
83 | addSubview(descriptionLabel)
84 |
85 | descriptionLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 10).isActive = true
86 | descriptionLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
87 | descriptionLabel.leftAnchor.constraint(equalTo: priceLabel.rightAnchor).isActive = true
88 | descriptionLabel.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
89 |
90 | addSubview(ratingView)
91 |
92 | ratingView.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 0).isActive = true
93 | ratingView.heightAnchor.constraint(equalToConstant: 20).isActive = true
94 | ratingView.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
95 | ratingView.widthAnchor.constraint(equalToConstant: ratingView.starSize * CGFloat(ratingView.stars.count)).isActive = true
96 |
97 | addSubview(reviewCountLabel)
98 |
99 | reviewCountLabel.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 0).isActive = true
100 | reviewCountLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
101 | reviewCountLabel.leftAnchor.constraint(equalTo: ratingView.rightAnchor, constant: 5).isActive = true
102 | reviewCountLabel.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
103 |
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbHomeItemTableCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbHomeItemTableCell.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 7/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbHomeItemTableCell: BaseTableCell {
12 |
13 | var home: AirbnbHome? {
14 | didSet {
15 | homeImageView.image = UIImage(named: home!.imageName)
16 | priceLabel.text = "$\(home!.price)"
17 | descriptionLabel.text = home?.homeDescription
18 | reviewLabel.text = "\(home!.reviewCount) Reviews"
19 | }
20 | }
21 |
22 | var homeDescription: String? {
23 | didSet {
24 | descriptionLabel.text = homeDescription
25 | }
26 | }
27 |
28 | var homeImageView: UIImageView = {
29 | let view = UIImageView()
30 | view.translatesAutoresizingMaskIntoConstraints = false
31 | view.contentMode = .scaleAspectFill
32 | view.clipsToBounds = true
33 | return view
34 | }()
35 |
36 | var priceLabel: UILabel = {
37 | let view = UILabel()
38 | view.translatesAutoresizingMaskIntoConstraints = false
39 | view.font = UIFont.boldSystemFont(ofSize: 14)
40 | view.textColor = UIColor.black
41 | return view
42 | }()
43 |
44 | var descriptionLabel: UILabel = {
45 | let view = UILabel()
46 | view.translatesAutoresizingMaskIntoConstraints = false
47 | view.font = UIFont.systemFont(ofSize: 14)
48 | view.textColor = UIColor.gray
49 | return view
50 | }()
51 |
52 | var reviewLabel: UILabel = {
53 | let view = UILabel()
54 | view.translatesAutoresizingMaskIntoConstraints = false
55 | view.font = UIFont.boldSystemFont(ofSize: 10)
56 | view.textColor = UIColor.darkGray
57 | return view
58 | }()
59 |
60 | override func setupViews() {
61 |
62 | addSubview(homeImageView)
63 |
64 | homeImageView.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true
65 | homeImageView.heightAnchor.constraint(equalToConstant: 250).isActive = true
66 | homeImageView.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
67 | homeImageView.rightAnchor.constraint(equalTo: rightAnchor, constant: -15).isActive = true
68 |
69 | addSubview(priceLabel)
70 |
71 | priceLabel.topAnchor.constraint(equalTo: homeImageView.bottomAnchor, constant: 10).isActive = true
72 | priceLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
73 | priceLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
74 | priceLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true
75 |
76 | addSubview(descriptionLabel)
77 |
78 | descriptionLabel.topAnchor.constraint(equalTo: homeImageView.bottomAnchor, constant: 10).isActive = true
79 | descriptionLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
80 | descriptionLabel.leftAnchor.constraint(equalTo: priceLabel.rightAnchor).isActive = true
81 | descriptionLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -15).isActive = true
82 |
83 | addSubview(reviewLabel)
84 |
85 | reviewLabel.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 0).isActive = true
86 | reviewLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
87 | reviewLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
88 | reviewLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -15).isActive = true
89 |
90 |
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbIconLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbIconLabel.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 15/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbIconLabel: UIView {
12 |
13 | var iconView: UIImageView = {
14 | let view = UIImageView()
15 | view.translatesAutoresizingMaskIntoConstraints = false
16 | view.contentMode = .scaleAspectFill
17 | return view
18 | }()
19 |
20 | var labelView: UILabel = {
21 | let view = UILabel()
22 | view.translatesAutoresizingMaskIntoConstraints = false
23 | view.font = UIFont.systemFont(ofSize: 16)
24 | view.textColor = UIColor.black
25 | return view
26 | }()
27 |
28 | override init(frame: CGRect) {
29 | super.init(frame: frame)
30 |
31 | addSubview(labelView)
32 |
33 | labelView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
34 | labelView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
35 | labelView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
36 | labelView.heightAnchor.constraint(equalToConstant: 20).isActive = true
37 |
38 | addSubview(iconView)
39 |
40 | iconView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
41 | iconView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
42 | iconView.bottomAnchor.constraint(equalTo: labelView.topAnchor).isActive = true
43 | iconView.topAnchor.constraint(equalTo: topAnchor).isActive = true
44 |
45 | }
46 |
47 | required init?(coder aDecoder: NSCoder) {
48 | fatalError("init(coder:) has not been implemented")
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbMainController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbMainController.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 3/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbMainController: UITabBarController {
12 |
13 | let AIRBNB_COLOR = UIColor(r: 255, g: 90, b: 95)
14 |
15 | var tabBarHeight: CGFloat = 60
16 | var tabBarTextAttributesNormal = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 8), NSAttributedStringKey.foregroundColor: UIColor.black]
17 | var tabBarTextAttributesSelected = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 8), NSAttributedStringKey.foregroundColor: UIColor(r: 255, g: 90, b: 95)]
18 |
19 | var tabBarSeparator: UIView = {
20 | let view = UIView()
21 | view.translatesAutoresizingMaskIntoConstraints = false
22 | view.backgroundColor = UIColor.lightGray
23 | return view
24 | }()
25 |
26 | var exploreTabItem: UITabBarItem = {
27 | let icon = UIImage(named: "Search")
28 | let tab = UITabBarItem(title: "EXPLORE", image: icon?.tint(with: .black).withRenderingMode(.alwaysOriginal), selectedImage: icon)
29 | tab.titlePositionAdjustment = UIOffsetMake(0, -5)
30 | return tab
31 | }()
32 |
33 | lazy var exploreController: AirbnbExploreController = {
34 | let controller = AirbnbExploreController()
35 | controller.tabBarItem = self.exploreTabItem
36 | return controller
37 | }()
38 |
39 | var savedTabItem: UITabBarItem = {
40 | let icon = UIImage(named: "Heart")
41 | let tab = UITabBarItem(title: "SAVED", image: icon?.tint(with: .black).withRenderingMode(.alwaysOriginal), selectedImage: icon)
42 | tab.titlePositionAdjustment = UIOffsetMake(0, -5)
43 | return tab
44 | }()
45 |
46 | lazy var savedController: UIViewController = {
47 | let controller = UIViewController()
48 | controller.tabBarItem = self.savedTabItem
49 | return controller
50 | }()
51 |
52 | var tripsTabItem: UITabBarItem = {
53 | let icon = UIImage(named: "Bed")
54 | let tab = UITabBarItem(title: "TRIPS", image: icon?.tint(with: .black).withRenderingMode(.alwaysOriginal), selectedImage: icon)
55 | tab.titlePositionAdjustment = UIOffsetMake(0, -5)
56 | return tab
57 | }()
58 |
59 | lazy var tripsController: AirbnbMapController = {
60 | let controller = AirbnbMapController()
61 | controller.tabBarItem = self.tripsTabItem
62 | return controller
63 | }()
64 |
65 | var inboxTabItem: UITabBarItem = {
66 | let icon = UIImage(named: "Message")
67 | let tab = UITabBarItem(title: "INBOX", image: icon?.tint(with: .black).withRenderingMode(.alwaysOriginal), selectedImage: icon)
68 | tab.titlePositionAdjustment = UIOffsetMake(0, -5)
69 | return tab
70 | }()
71 |
72 | lazy var inboxController: UIViewController = {
73 | let controller = UIViewController()
74 | controller.tabBarItem = self.inboxTabItem
75 | return controller
76 | }()
77 |
78 | var profileTabItem: UITabBarItem = {
79 | let icon = UIImage(named: "Profile")
80 | let tab = UITabBarItem(title: "PROFILE", image: icon?.tint(with: .black).withRenderingMode(.alwaysOriginal), selectedImage: icon)
81 | tab.titlePositionAdjustment = UIOffsetMake(0, -5)
82 | return tab
83 | }()
84 |
85 | lazy var profileController: UIViewController = {
86 | let controller = UIViewController()
87 | controller.tabBarItem = self.profileTabItem
88 | return controller
89 | }()
90 |
91 | override func viewDidLoad() {
92 | super.viewDidLoad()
93 |
94 | viewControllers = [exploreController, savedController, tripsController, inboxController, profileController]
95 | delegate = self
96 |
97 | setupTabBar()
98 | }
99 |
100 | override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
101 | return selectedViewController?.preferredStatusBarUpdateAnimation ?? .fade
102 | }
103 |
104 | override var preferredStatusBarStyle: UIStatusBarStyle {
105 | return selectedViewController?.preferredStatusBarStyle ?? .default
106 | }
107 |
108 | override var prefersStatusBarHidden: Bool {
109 | return selectedViewController?.prefersStatusBarHidden ?? false
110 | }
111 |
112 | func setupTabBar() {
113 |
114 | // add separator line
115 | tabBar.clipsToBounds = true // hide default top border
116 | tabBar.addSubview(tabBarSeparator)
117 |
118 | tabBarSeparator.widthAnchor.constraint(equalTo: tabBar.widthAnchor).isActive = true
119 | tabBarSeparator.heightAnchor.constraint(equalToConstant: 1).isActive = true
120 | tabBarSeparator.centerXAnchor.constraint(equalTo: tabBar.centerXAnchor).isActive = true
121 | tabBarSeparator.topAnchor.constraint(equalTo: tabBar.topAnchor).isActive = true
122 |
123 | tabBar.tintColor = AIRBNB_COLOR
124 | tabBar.barTintColor = UIColor.white
125 | tabBar.isTranslucent = false
126 |
127 | UITabBarItem.appearance().setTitleTextAttributes(tabBarTextAttributesNormal, for: .normal)
128 | UITabBarItem.appearance().setTitleTextAttributes(tabBarTextAttributesSelected, for: .selected)
129 | }
130 |
131 | }
132 |
133 | extension AirbnbMainController: UITabBarControllerDelegate {
134 |
135 | }
136 |
137 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbMapController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbMapController.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 20/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import MapKit
11 |
12 | class AirbnbMapController: UIViewController {
13 |
14 | let cellID = "cellID"
15 |
16 | let locations = ["Oslo", "Stockholm", "Barcelona", "Madrid", "Copenhagen", "London", "Milan", "Rome", "Hamburg"]
17 |
18 | lazy var items: [AirbnbHome] = {
19 | var arr = [AirbnbHome]()
20 | for i in 5..<11 {
21 | let location = self.locations[Int(arc4random_uniform(UInt32(self.locations.count)))]
22 | let item = AirbnbHome(imageName: "home-\(i)", description: "Entire home in \(location)", price: Int(arc4random_uniform(100) + 200), reviewCount: Int(arc4random_uniform(300) + 1), rating: Double(arc4random()) / Double(UINT32_MAX) + 4)
23 | arr.append(item)
24 | }
25 | return arr
26 | }()
27 |
28 | var mapView: MKMapView = {
29 | let view = MKMapView()
30 | view.translatesAutoresizingMaskIntoConstraints = false
31 | return view
32 | }()
33 |
34 | lazy var thumbnailCollectionView: UICollectionView = {
35 | let layout = UICollectionViewFlowLayout()
36 | layout.scrollDirection = .horizontal
37 | layout.minimumInteritemSpacing = 0
38 | layout.minimumLineSpacing = 0
39 | layout.itemSize = CGSize(width: 200, height: 185)
40 |
41 | let view = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
42 | view.translatesAutoresizingMaskIntoConstraints = false
43 | view.backgroundColor = UIColor.white
44 | view.register(AirbnbMapItemCell.self, forCellWithReuseIdentifier: self.cellID)
45 | view.showsHorizontalScrollIndicator = false
46 | view.dataSource = self
47 | return view
48 | }()
49 |
50 | override func viewDidLoad() {
51 | super.viewDidLoad()
52 |
53 | view.addSubview(thumbnailCollectionView)
54 |
55 | thumbnailCollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
56 | thumbnailCollectionView.heightAnchor.constraint(equalToConstant: 185).isActive = true
57 | thumbnailCollectionView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
58 | thumbnailCollectionView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
59 |
60 | view.addSubview(mapView)
61 |
62 | mapView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
63 | mapView.bottomAnchor.constraint(equalTo: thumbnailCollectionView.topAnchor).isActive = true
64 | mapView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
65 | mapView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
66 | }
67 |
68 | }
69 |
70 | extension AirbnbMapController: UICollectionViewDataSource {
71 | func numberOfSections(in collectionView: UICollectionView) -> Int {
72 | return 1
73 | }
74 |
75 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
76 | return items.count
77 | }
78 |
79 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
80 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! AirbnbMapItemCell
81 |
82 | cell.home = items[indexPath.item]
83 |
84 | return cell
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbMapItemCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbMapItemCell.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 3/7/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbMapItemCell: BaseCollectionCell {
12 |
13 | var home: AirbnbHome? {
14 | didSet {
15 | imageView.image = UIImage(named: home!.imageName)
16 | priceLabel.text = "$\(home!.price)"
17 | descriptionLabel.text = home?.homeDescription
18 | reviewCountLabel.text = "\(home!.reviewCount) Reviews"
19 | ratingView.rating = home!.rating
20 | }
21 | }
22 |
23 | var homeDescription: String? {
24 | didSet {
25 | descriptionLabel.text = homeDescription
26 | }
27 | }
28 |
29 | var imageView: UIImageView = {
30 | let view = UIImageView()
31 | view.translatesAutoresizingMaskIntoConstraints = false
32 | view.contentMode = .scaleAspectFill
33 | view.clipsToBounds = true
34 | return view
35 | }()
36 |
37 | var priceLabel: UILabel = {
38 | let view = UILabel()
39 | view.translatesAutoresizingMaskIntoConstraints = false
40 | view.font = UIFont.boldSystemFont(ofSize: 14)
41 | view.textColor = UIColor.black
42 | return view
43 | }()
44 |
45 | var descriptionLabel: UILabel = {
46 | let view = UILabel()
47 | view.translatesAutoresizingMaskIntoConstraints = false
48 | view.font = UIFont.systemFont(ofSize: 14)
49 | view.textColor = UIColor.gray
50 | return view
51 | }()
52 |
53 | var ratingView: AirbnbReview = {
54 | let view = AirbnbReview()
55 | view.translatesAutoresizingMaskIntoConstraints = false
56 | return view
57 | }()
58 |
59 | var reviewCountLabel: UILabel = {
60 | let view = UILabel()
61 | view.translatesAutoresizingMaskIntoConstraints = false
62 | view.font = UIFont.boldSystemFont(ofSize: 10)
63 | view.textColor = UIColor.darkGray
64 | return view
65 | }()
66 |
67 | override func setupViews() {
68 |
69 | addSubview(imageView)
70 |
71 | imageView.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true
72 | imageView.heightAnchor.constraint(equalToConstant: 120).isActive = true
73 | imageView.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
74 | imageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
75 |
76 | addSubview(priceLabel)
77 |
78 | priceLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 5).isActive = true
79 | priceLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
80 | priceLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
81 | priceLabel.widthAnchor.constraint(equalToConstant: 40).isActive = true
82 |
83 | addSubview(descriptionLabel)
84 |
85 | descriptionLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 5).isActive = true
86 | descriptionLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
87 | descriptionLabel.leftAnchor.constraint(equalTo: priceLabel.rightAnchor).isActive = true
88 | descriptionLabel.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
89 |
90 | addSubview(ratingView)
91 |
92 | ratingView.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 0).isActive = true
93 | ratingView.heightAnchor.constraint(equalToConstant: 20).isActive = true
94 | ratingView.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
95 | ratingView.widthAnchor.constraint(equalToConstant: ratingView.starSize * CGFloat(ratingView.stars.count)).isActive = true
96 |
97 | addSubview(reviewCountLabel)
98 |
99 | reviewCountLabel.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 0).isActive = true
100 | reviewCountLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
101 | reviewCountLabel.leftAnchor.constraint(equalTo: ratingView.rightAnchor, constant: 5).isActive = true
102 | reviewCountLabel.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
103 |
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbPageTabItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbPageTabItem.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 13/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol AirbnbPageTabItemDelegate {
12 | func didSelect(tabItem: AirbnbPageTabItem, completion: (() -> Void)?)
13 | }
14 |
15 | class AirbnbPageTabItem: BasePageTabItemView {
16 |
17 | var delegate: AirbnbPageTabItemDelegate?
18 |
19 | var title: String = "" {
20 | didSet {
21 | titleButton.setTitle(title.uppercased(), for: .normal)
22 | }
23 | }
24 | var titleColor: UIColor = UIColor.white {
25 | didSet {
26 | titleButton.setTitleColor(titleColor, for: .normal)
27 | }
28 | }
29 |
30 | var selectedTitleColor: UIColor = UIColor.white {
31 | didSet {
32 | if isSelected {
33 | titleButton.setTitleColor(selectedTitleColor, for: .normal)
34 | }
35 | }
36 | }
37 |
38 | var isSelected: Bool = false {
39 | didSet {
40 | if isSelected {
41 |
42 | } else {
43 |
44 | }
45 | }
46 | }
47 |
48 | lazy var titleButton: UIButton = {
49 | let view = UIButton()
50 | view.translatesAutoresizingMaskIntoConstraints = false
51 | view.setTitleColor(self.titleColor, for: .normal)
52 | view.titleLabel?.textAlignment = .center
53 | view.titleLabel?.font = UIFont.boldSystemFont(ofSize: 12)
54 | view.addTarget(self, action: #selector(AirbnbPageTabItem.didSelect), for: .touchUpInside)
55 | return view
56 | }()
57 |
58 | var titleLabelWidthAnchor: NSLayoutConstraint?
59 |
60 | override func setupViews() {
61 | super.setupViews()
62 |
63 | addSubview(titleButton)
64 |
65 | titleButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
66 | titleButton.topAnchor.constraint(equalTo: topAnchor).isActive = true
67 | titleButton.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
68 | titleButton.widthAnchor.constraint(equalTo: widthAnchor, constant: -30).isActive = true
69 | }
70 |
71 | @objc func didSelect() {
72 | if let handler = delegate {
73 | handler.didSelect(tabItem: self, completion: nil)
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/AirbnbReview.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbReview.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 13/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbReview: UIView {
12 |
13 | var starSize: CGFloat = 12
14 |
15 | var rating: Double = 0 {
16 | didSet {
17 | var val = rating
18 | for i in 0..= 0.75 {
20 | stars[i].type = .full
21 | val -= 1
22 | } else if val >= 0.25 {
23 | stars[i].type = .halfEmpty
24 | val -= 0.5
25 | } else {
26 | stars[i].type = .empty
27 | }
28 | }
29 | }
30 | }
31 |
32 | var stars: [AirbnbStar] = {
33 | var arr = [AirbnbStar]()
34 | for _ in 0..<5 {
35 | let view = AirbnbStar()
36 | view.translatesAutoresizingMaskIntoConstraints = false
37 | arr.append(view)
38 | }
39 | return arr
40 | }()
41 |
42 | override init(frame: CGRect) {
43 | super.init(frame: frame)
44 |
45 | for i in 0.. Bool {
18 | // Override point for customization after application launch.
19 | UIApplication.shared.statusBarStyle = .lightContent
20 |
21 | window = UIWindow(frame: UIScreen.main.bounds)
22 | window?.rootViewController = AirbnbMainController()
23 | window?.makeKeyAndVisible()
24 | return true
25 | }
26 |
27 | func applicationWillResignActive(_ application: UIApplication) {
28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
29 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
30 | }
31 |
32 | func applicationDidEnterBackground(_ application: UIApplication) {
33 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
35 | }
36 |
37 | func applicationWillEnterForeground(_ application: UIApplication) {
38 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
39 | }
40 |
41 | func applicationDidBecomeActive(_ application: UIApplication) {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 | func applicationWillTerminate(_ application: UIApplication) {
46 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
47 | }
48 |
49 |
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Back.imageset/Back-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Back.imageset/Back-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Back.imageset/Back-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Back.imageset/Back-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Back.imageset/Back-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Back.imageset/Back-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Back.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Back-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Back-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Back-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Bed.imageset/Bed-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Bed.imageset/Bed-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Bed.imageset/Bed-50 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Bed.imageset/Bed-50 (1).png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Bed.imageset/Bed-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Bed.imageset/Bed-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Bed.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Bed-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Bed-50 (1).png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Bed-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Collapse.imageset/Collapse Arrow-25 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Collapse.imageset/Collapse Arrow-25 (1).png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Collapse.imageset/Collapse Arrow-50 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Collapse.imageset/Collapse Arrow-50 (1).png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Collapse.imageset/Collapse Arrow-75 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Collapse.imageset/Collapse Arrow-75 (1).png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Collapse.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Collapse Arrow-25 (1).png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Collapse Arrow-50 (1).png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Collapse Arrow-75 (1).png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Door.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Door Opened-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Door Opened-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Door Opened-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Door.imageset/Door Opened-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Door.imageset/Door Opened-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Door.imageset/Door Opened-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Door.imageset/Door Opened-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Door.imageset/Door Opened-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Door.imageset/Door Opened-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Expand.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Expand Arrow-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Expand Arrow-50 (1).png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Expand Arrow-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Expand.imageset/Expand Arrow-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Expand.imageset/Expand Arrow-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Expand.imageset/Expand Arrow-50 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Expand.imageset/Expand Arrow-50 (1).png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Expand.imageset/Expand Arrow-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Expand.imageset/Expand Arrow-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Globe.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Globe Earth-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Globe Earth-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Globe Earth-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Globe.imageset/Globe Earth-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Globe.imageset/Globe Earth-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Globe.imageset/Globe Earth-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Globe.imageset/Globe Earth-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Globe.imageset/Globe Earth-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Globe.imageset/Globe Earth-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Heart.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Hearts-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Hearts-50 (1).png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Hearts-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Heart.imageset/Hearts-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Heart.imageset/Hearts-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Heart.imageset/Hearts-50 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Heart.imageset/Hearts-50 (1).png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Heart.imageset/Hearts-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Heart.imageset/Hearts-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Message.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Message-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Message-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Message-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Message.imageset/Message-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Message.imageset/Message-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Message.imageset/Message-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Message.imageset/Message-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Message.imageset/Message-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Message.imageset/Message-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Profile.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "User-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "User-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "User-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Profile.imageset/User-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Profile.imageset/User-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Profile.imageset/User-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Profile.imageset/User-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Profile.imageset/User-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Profile.imageset/User-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Search.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Search-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Search-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Search-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Search.imageset/Search-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Search.imageset/Search-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Search.imageset/Search-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Search.imageset/Search-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Search.imageset/Search-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Search.imageset/Search-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Shower.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Shower and Tub-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Shower and Tub-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Shower and Tub-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Shower.imageset/Shower and Tub-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Shower.imageset/Shower and Tub-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Shower.imageset/Shower and Tub-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Shower.imageset/Shower and Tub-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Shower.imageset/Shower and Tub-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Shower.imageset/Shower and Tub-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Empty.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Star-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Star-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Star-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Empty.imageset/Star-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Empty.imageset/Star-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Empty.imageset/Star-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Empty.imageset/Star-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Empty.imageset/Star-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Empty.imageset/Star-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Filled.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Star Filled-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Star Filled-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Star Filled-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Filled.imageset/Star Filled-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Filled.imageset/Star Filled-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Filled.imageset/Star Filled-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Filled.imageset/Star Filled-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Filled.imageset/Star Filled-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Filled.imageset/Star Filled-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Half Empty.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Star Half Empty-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Star Half Empty-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Star Half Empty-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Half Empty.imageset/Star Half Empty-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Half Empty.imageset/Star Half Empty-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Half Empty.imageset/Star Half Empty-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Half Empty.imageset/Star Half Empty-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Star Half Empty.imageset/Star Half Empty-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Star Half Empty.imageset/Star Half Empty-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Upload.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Upload-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Upload-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Upload-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Upload.imageset/Upload-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Upload.imageset/Upload-25.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Upload.imageset/Upload-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Upload.imageset/Upload-50.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/Upload.imageset/Upload-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/Upload.imageset/Upload-75.png
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-1.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-1.imageset/home-1.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-1.imageset/home-1.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-10.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-10.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-10.imageset/home-10.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-10.imageset/home-10.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-2.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-2.imageset/home-2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-2.imageset/home-2.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-3.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-3.imageset/home-3.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-3.imageset/home-3.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-4.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-4.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-4.imageset/home-4.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-4.imageset/home-4.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-5.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-5.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-5.imageset/home-5.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-5.imageset/home-5.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-6.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-6.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-6.imageset/home-6.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-6.imageset/home-6.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-7.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-7.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-7.imageset/home-7.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-7.imageset/home-7.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-8.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-8.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-8.imageset/home-8.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-8.imageset/home-8.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-9.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "home-9.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/home-9.imageset/home-9.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/home-9.imageset/home-9.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/profpic.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "profpic.jpeg",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Assets.xcassets/profpic.imageset/profpic.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-main/airbnb-main/Assets.xcassets/profpic.imageset/profpic.jpeg
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/BaseCollectionCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseCollectionCell.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 3/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BaseCollectionCell: UICollectionViewCell {
12 |
13 | override init(frame: CGRect) {
14 | super.init(frame: frame)
15 | setupViews()
16 | }
17 |
18 | required init?(coder aDecoder: NSCoder) {
19 | fatalError("init(coder:) has not been implemented")
20 | }
21 |
22 | func setupViews() {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/BasePageTabItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BasePageTabView.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 13/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BasePageTabItemView: UIView {
12 |
13 | override init(frame: CGRect) {
14 | super.init(frame: frame)
15 |
16 | }
17 |
18 | override func layoutSubviews() {
19 | setupViews()
20 | }
21 |
22 | required init?(coder aDecoder: NSCoder) {
23 | fatalError("init(coder:) has not been implemented")
24 | }
25 |
26 | func setupViews() {
27 |
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/BaseTableCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseCell.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 7/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BaseTableCell: UITableViewCell {
12 |
13 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
14 | super.init(style: style, reuseIdentifier: reuseIdentifier)
15 | setupViews()
16 | }
17 |
18 | required init?(coder aDecoder: NSCoder) {
19 | fatalError("init(coder:) has not been implemented")
20 | }
21 |
22 | func setupViews() {
23 |
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/BaseTableController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseTableController.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 13/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol BaseTableControllerDelegate {
12 | var headerViewHeightConstraint: NSLayoutConstraint? { get set }
13 | var headerView: AirbnbExploreHeaderView { get set }
14 | var maxHeaderHeight: CGFloat { get }
15 | var midHeaderHeight: CGFloat { get }
16 | var minHeaderHeight: CGFloat { get }
17 |
18 | func layoutViews()
19 | func updateStatusBar()
20 | }
21 |
22 | class BaseTableController: UIViewController {
23 | var headerDelegate: BaseTableControllerDelegate!
24 | var previousScrollOffset: CGFloat = 0
25 |
26 | var isHiddenStatusBar: Bool = false
27 | var statusBarStyle: UIStatusBarStyle = .lightContent
28 |
29 | override func didMove(toParentViewController parent: UIViewController?) {
30 | if let del = parent as? BaseTableControllerDelegate {
31 | self.headerDelegate = del
32 | }
33 | }
34 |
35 | override func viewWillDisappear(_ animated: Bool) {
36 | super.viewWillDisappear(animated)
37 | UIApplication.shared.statusBarStyle = .default
38 | }
39 |
40 | override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
41 | return .fade
42 | }
43 |
44 | override var preferredStatusBarStyle: UIStatusBarStyle {
45 | return statusBarStyle
46 | }
47 |
48 | override var prefersStatusBarHidden: Bool {
49 | return isHiddenStatusBar
50 | }
51 |
52 | func setStatusBarHidden(_ isHidden: Bool, withStyle style: UIStatusBarStyle) {
53 | if isHidden != isHiddenStatusBar || statusBarStyle != style {
54 | statusBarStyle = style
55 | isHiddenStatusBar = isHidden
56 |
57 | UIView.animate(withDuration: 0.5, animations: {
58 | self.headerDelegate.updateStatusBar()
59 | })
60 | }
61 | }
62 |
63 | func updateStatusBar() {
64 | let curHeight = headerDelegate.headerViewHeightConstraint!.constant
65 | if curHeight == headerDelegate.minHeaderHeight {
66 | setStatusBarHidden(false, withStyle: .default)
67 | } else if curHeight > headerDelegate.minHeaderHeight, curHeight < headerDelegate.midHeaderHeight {
68 | setStatusBarHidden(true, withStyle: .lightContent)
69 | } else {
70 | setStatusBarHidden(false, withStyle: .lightContent)
71 | }
72 | }
73 | }
74 |
75 | extension BaseTableController: UITableViewDelegate {
76 | func scrollViewDidScroll(_ scrollView: UIScrollView) {
77 | let absoluteTop: CGFloat = 0
78 | let absoluteBottom: CGFloat = max(0, scrollView.contentSize.height - scrollView.frame.height)
79 |
80 | let scrollDif = scrollView.contentOffset.y - previousScrollOffset
81 | let isScrollUp = scrollDif < 0 && scrollView.contentOffset.y < absoluteBottom // swipe down - header expands
82 | let isScrollDown = scrollDif > 0 && scrollView.contentOffset.y > absoluteTop // swipe up - header shrinks
83 |
84 | var newHeight = headerDelegate.headerViewHeightConstraint!.constant
85 | if isScrollUp {
86 | newHeight = min(headerDelegate.maxHeaderHeight, (headerDelegate.headerViewHeightConstraint!.constant + abs(scrollDif)))
87 | } else if isScrollDown {
88 | newHeight = max(headerDelegate.minHeaderHeight, (headerDelegate.headerViewHeightConstraint!.constant - abs(scrollDif)))
89 | }
90 |
91 | if newHeight != headerDelegate.headerViewHeightConstraint!.constant {
92 | headerDelegate.headerViewHeightConstraint?.constant = newHeight
93 | headerDelegate.headerView.updateHeader(newHeight: newHeight, offset: scrollDif)
94 | setScrollPosition(scrollView, toPosition: previousScrollOffset)
95 | updateStatusBar()
96 | }
97 |
98 | previousScrollOffset = scrollView.contentOffset.y
99 | }
100 |
101 | func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
102 | scrollViewDidStopScrolling(scrollView)
103 | }
104 |
105 | func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
106 | if !decelerate {
107 | scrollViewDidStopScrolling(scrollView)
108 | }
109 | }
110 |
111 | func setScrollPosition(_ scrollView: UIScrollView, toPosition position: CGFloat) {
112 | scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x, y: position)
113 | }
114 |
115 | func scrollViewDidStopScrolling(_ scrollView: UIScrollView) {
116 | let curHeight = headerDelegate.headerViewHeightConstraint!.constant
117 | if curHeight < headerDelegate.midHeaderHeight {
118 | setHeaderHeight(scrollView, height: headerDelegate.minHeaderHeight)
119 | } else if curHeight < headerDelegate.maxHeaderHeight - headerDelegate.headerView.headerInputHeight {
120 | setHeaderHeight(scrollView, height: headerDelegate.midHeaderHeight)
121 | } else {
122 | setHeaderHeight(scrollView, height: headerDelegate.maxHeaderHeight)
123 | }
124 |
125 | updateStatusBar()
126 | }
127 |
128 | func setHeaderHeight(_ scrollView: UIScrollView, height: CGFloat) {
129 | self.headerDelegate.layoutViews()
130 | UIView.animate(withDuration: 0.2, animations: {
131 | self.headerDelegate.headerViewHeightConstraint?.constant = height
132 | self.headerDelegate.headerView.updateHeader(newHeight: height, offset: scrollView.contentOffset.y - self.previousScrollOffset)
133 | self.headerDelegate.layoutViews()
134 | })
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UIViewControllerBasedStatusBarAppearance
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/String.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 13/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension String {
12 | func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
13 | let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
14 | let boundingBox = (self as NSString).boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)
15 | return boundingBox.height
16 | }
17 |
18 | func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
19 | let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
20 | let boundingBox = (self as NSString).boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)
21 | return boundingBox.width
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/Theme.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Theme.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 29/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class Theme {
12 |
13 | static let PRIMARY_COLOR = UIColor(r: 0, g: 132, b: 137)
14 | static let PRIMARY_DARK_COLOR = UIColor(r: 15, g: 114, b: 118)
15 | static let SECONDARY_COLOR = UIColor(r: 65, g: 171, b: 175)
16 | static let TERTIARY_COLOR = UIColor(r: 255, g: 90, b: 95)
17 |
18 | static let INPUT_COLOR = UIColor(r: 37, g: 145, b: 146)
19 | static let DARK_GRAY = UIColor(r: 75, g: 75, b: 75)
20 | static let GRAY = UIColor(r: 150, g: 150, b: 150)
21 | static let LIGHT_GRAY = UIColor(r: 236, g: 236, b: 236)
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/UIColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 9/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | convenience init(hex: String) {
13 | var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
14 | if (cString.hasPrefix("#")) {
15 | cString = String(cString.suffix(from: cString.startIndex))
16 | }
17 |
18 | if ((cString.count) != 6) {
19 | self.init()
20 | } else {
21 | var rgbValue:UInt32 = 0
22 | Scanner(string: cString).scanHexInt32(&rgbValue)
23 |
24 | self.init(
25 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
26 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
27 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
28 | alpha: CGFloat(1.0)
29 | )
30 | }
31 | }
32 |
33 | convenience init(r: CGFloat, g: CGFloat, b: CGFloat) {
34 | self.init(red: CGFloat(r / 255), green: CGFloat(g / 255), blue: CGFloat(b / 255), alpha: CGFloat(1))
35 | }
36 |
37 | static func fade(fromColor: UIColor, toColor: UIColor, withPercentage: CGFloat) -> UIColor {
38 |
39 | var fromRed: CGFloat = 0.0
40 | var fromGreen: CGFloat = 0.0
41 | var fromBlue: CGFloat = 0.0
42 | var fromAlpha: CGFloat = 0.0
43 |
44 | fromColor.getRed(&fromRed, green: &fromGreen, blue: &fromBlue, alpha: &fromAlpha)
45 |
46 | var toRed: CGFloat = 0.0
47 | var toGreen: CGFloat = 0.0
48 | var toBlue: CGFloat = 0.0
49 | var toAlpha: CGFloat = 0.0
50 |
51 | toColor.getRed(&toRed, green: &toGreen, blue: &toBlue, alpha: &toAlpha)
52 |
53 | //calculate the actual RGBA values of the fade colour
54 | let red = (toRed - fromRed) * withPercentage + fromRed;
55 | let green = (toGreen - fromGreen) * withPercentage + fromGreen;
56 | let blue = (toBlue - fromBlue) * withPercentage + fromBlue;
57 | let alpha = (toAlpha - fromAlpha) * withPercentage + fromAlpha;
58 |
59 | // return the fade colour
60 | return UIColor(red: red, green: green, blue: blue, alpha: alpha)
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/UIImage.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 12/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIImage {
12 | func tint(with color: UIColor) -> UIImage {
13 | var image = withRenderingMode(.alwaysTemplate)
14 | UIGraphicsBeginImageContextWithOptions(size, false, scale)
15 | color.set()
16 |
17 | image.draw(in: CGRect(origin: .zero, size: size))
18 | image = UIGraphicsGetImageFromCurrentImageContext()!
19 | UIGraphicsEndImageContext()
20 | return image
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/UITabBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UITabBar.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 12/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UITabBar {
12 |
13 | override open func sizeThatFits(_ size: CGSize) -> CGSize {
14 | var sizeThatFits = super.sizeThatFits(size)
15 | sizeThatFits.height = 55 // adjust your size here
16 | return sizeThatFits
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/airbnb-main/airbnb-main/VerticalAlignLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VerticalAlignLabel.swift
3 | // airbnb-main
4 | //
5 | // Created by Yonas Stephen on 13/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class VerticalAlignLabel: UILabel {
12 | enum VerticalAlignment {
13 | case top
14 | case middle
15 | case bottom
16 | }
17 |
18 | var verticalAlignment : VerticalAlignment = .top {
19 | didSet {
20 | setNeedsDisplay()
21 | }
22 | }
23 |
24 | override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
25 | let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
26 |
27 | if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft {
28 | switch verticalAlignment {
29 | case .top:
30 | return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
31 | case .middle:
32 | return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
33 | case .bottom:
34 | return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
35 | }
36 | } else {
37 | switch verticalAlignment {
38 | case .top:
39 | return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
40 | case .middle:
41 | return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
42 | case .bottom:
43 | return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
44 | }
45 | }
46 | }
47 |
48 | override public func drawText(in rect: CGRect) {
49 | let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
50 | super.drawText(in: r)
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/AirbnbOccupantFilter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbOccupantFilter.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 4/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbOccupantFilter: UIView {
12 |
13 | public var delegate: UIViewController?
14 |
15 | var adultCount: Int = 1
16 | var childrenCount: Int = 0
17 | var infantCount: Int = 0
18 | var hasPet: Bool = false
19 |
20 | // MARK: - View Components
21 |
22 | var occupantInputButton: UIButton = {
23 | let btn = UIButton()
24 | btn.translatesAutoresizingMaskIntoConstraints = false
25 | btn.backgroundColor = Theme.PRIMARY_COLOR
26 | btn.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left
27 | btn.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
28 | btn.adjustsImageWhenHighlighted = false
29 | btn.addTarget(self, action: #selector(AirbnbOccupantFilter.showOccupantFilter), for: .touchUpInside)
30 |
31 | let img = UIImage(named: "Family", in: Bundle(for: AirbnbOccupantFilter.self), compatibleWith: nil)
32 | btn.setImage(img, for: .normal)
33 | btn.imageView?.contentMode = .scaleAspectFit
34 |
35 | btn.setTitle("1 guest", for: .normal)
36 | btn.setTitleColor(UIColor.white, for: .normal)
37 | btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 15)
38 | btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
39 | btn.titleLabel?.lineBreakMode = .byTruncatingTail
40 | return btn
41 | }()
42 |
43 | // MARK: - Initializations
44 |
45 | override init(frame: CGRect) {
46 | super.init(frame: frame)
47 | setupViews()
48 | }
49 |
50 | required init?(coder aDecoder: NSCoder) {
51 | fatalError("init(coder:) has not been implemented")
52 | }
53 |
54 | // MARK: - View Setups
55 |
56 | func setupViews() {
57 | addSubview(occupantInputButton)
58 |
59 | occupantInputButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
60 | occupantInputButton.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
61 | occupantInputButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
62 | occupantInputButton.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
63 |
64 | }
65 |
66 | // MARK: - Event Handlers
67 |
68 | func showOccupantFilter() {
69 | let occupantController = AirbnbOccupantFilterController(adultCount: adultCount, childrenCount: childrenCount, infantCount: infantCount, hasPet: hasPet)
70 | occupantController.delegate = self
71 | let navigationController = UINavigationController(rootViewController: occupantController)
72 | delegate?.present(navigationController, animated: true, completion: nil)
73 | }
74 | }
75 |
76 | extension AirbnbOccupantFilter: AirbnbOccupantFilterControllerDelegate {
77 | func occupantFilterController(_ occupantFilterController: AirbnbOccupantFilterController, didSaveAdult adult: Int, children: Int, infant: Int, pet: Bool) {
78 |
79 | self.adultCount = adult
80 | self.childrenCount = children
81 | self.infantCount = infant
82 | self.hasPet = pet
83 |
84 | let human = adult + children
85 | let infant = "\(infant > 0 ? (infant.description + " infant" + (infant > 1 ? "s" : "")) : "")"
86 | let pet = "\(pet ? "pets" : "")"
87 |
88 | let text = "\(human) guest\(human > 1 ? "s" : "")" + (infant != "" ? ", " + infant : "") + (pet != "" ? ", " + pet : "")
89 | occupantInputButton.setTitle(text, for: .normal)
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 4/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-25.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-50.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-75.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Checkmark-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Checkmark-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Checkmark-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Delete-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Delete-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Delete-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-25.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-50.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-75.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Family Man Woman-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Family Man Woman-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Family Man Woman-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-25.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-50.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-75.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Minus-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Minus-48.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Minus-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-25.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-48.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-75.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Plus Math-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Plus Math-48.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Plus Math-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-25.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-48.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-75.png
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/Theme.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Theme.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 4/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class Theme {
12 |
13 | static let PRIMARY_COLOR = UIColor(r: 0, g: 132, b: 137)
14 | static let SECONDARY_COLOR = UIColor(r: 65, g: 171, b: 175)
15 |
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/UIColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 4/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | convenience init(hex: String) {
13 | var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
14 | if (cString.hasPrefix("#")) {
15 | cString = cString.substring(from: cString.index(cString.startIndex, offsetBy: 1))
16 | }
17 |
18 | if ((cString.characters.count) != 6) {
19 | self.init()
20 | } else {
21 | var rgbValue:UInt32 = 0
22 | Scanner(string: cString).scanHexInt32(&rgbValue)
23 |
24 | self.init(
25 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
26 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
27 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
28 | alpha: CGFloat(1.0)
29 | )
30 | }
31 | }
32 |
33 | convenience init(r: CGFloat, g: CGFloat, b: CGFloat) {
34 | self.init(red: CGFloat(r / 255), green: CGFloat(g / 255), blue: CGFloat(b / 255), alpha: CGFloat(1))
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/UIImage.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 5/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIImage {
12 | func tint(with color: UIColor) -> UIImage {
13 | var image = withRenderingMode(.alwaysTemplate)
14 | UIGraphicsBeginImageContextWithOptions(size, false, scale)
15 | color.set()
16 |
17 | image.draw(in: CGRect(origin: .zero, size: size))
18 | image = UIGraphicsGetImageFromCurrentImageContext()!
19 | UIGraphicsEndImageContext()
20 | return image
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/airbnb-occupant-filter/airbnb-occupant-filter/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 4/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | lazy var occupantFilter: AirbnbOccupantFilter = {
14 | let btn = AirbnbOccupantFilter()
15 | btn.translatesAutoresizingMaskIntoConstraints = false
16 | btn.delegate = self
17 | return btn
18 | }()
19 |
20 | override func viewDidLoad() {
21 | super.viewDidLoad()
22 |
23 | view.addSubview(occupantFilter)
24 |
25 | occupantFilter.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
26 | occupantFilter.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
27 | occupantFilter.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
28 | occupantFilter.heightAnchor.constraint(equalToConstant: 50).isActive = true
29 |
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/AirbnbDatePicker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePicker.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 22/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class AirbnbDatePicker: UIView, AirbnbDatePickerDelegate {
12 |
13 | public var selectedStartDate: Date?
14 | public var selectedEndDate: Date?
15 | public var delegate: UIViewController?
16 |
17 | var dateFormatter: DateFormatter {
18 | get {
19 | let f = DateFormatter()
20 | f.dateFormat = "d MMM"
21 | return f
22 | }
23 | }
24 |
25 | public override init(frame: CGRect) {
26 | super.init(frame: frame)
27 | setupViews()
28 | }
29 |
30 | public required init?(coder aDecoder: NSCoder) {
31 | fatalError("init(coder:) has not been implemented")
32 | }
33 |
34 | public lazy var dateInputButton: UIButton = {
35 | let btn = UIButton()
36 | btn.translatesAutoresizingMaskIntoConstraints = false
37 | btn.backgroundColor = Theme.PRIMARY_COLOR
38 | btn.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left
39 | btn.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
40 | btn.adjustsImageWhenHighlighted = false
41 | btn.addTarget(self, action: #selector(AirbnbDatePicker.showDatePicker), for: .touchUpInside)
42 |
43 | let img = UIImage(named: "Calendar", in: Bundle(for: AirbnbDatePicker.self), compatibleWith: nil)
44 | btn.setImage(img, for: .normal)
45 | btn.imageView?.contentMode = .scaleAspectFit
46 |
47 | btn.setTitle("Anytime", for: .normal)
48 | btn.setTitleColor(UIColor.white, for: .normal)
49 | btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 15)
50 | btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
51 | btn.titleLabel?.lineBreakMode = .byTruncatingTail
52 |
53 | return btn
54 | }()
55 |
56 | func setupViews() {
57 | addSubview(dateInputButton)
58 |
59 | dateInputButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
60 | dateInputButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
61 | dateInputButton.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
62 | dateInputButton.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
63 | }
64 |
65 | @objc func showDatePicker() {
66 | let datePickerViewController = AirbnbDatePickerViewController(dateFrom: selectedStartDate, dateTo: selectedEndDate)
67 | datePickerViewController.delegate = self
68 | let navigationController = UINavigationController(rootViewController: datePickerViewController)
69 | delegate?.present(navigationController, animated: true, completion: nil)
70 | }
71 |
72 | public func datePickerController(_ datePickerController: AirbnbDatePickerViewController, didSaveStartDate startDate: Date?, endDate: Date?) {
73 | selectedStartDate = startDate
74 | selectedEndDate = endDate
75 |
76 | if selectedStartDate == nil && selectedEndDate == nil {
77 | dateInputButton.setTitle("Anytime", for: .normal)
78 |
79 | } else {
80 | dateInputButton.setTitle("\(dateFormatter.string(from: startDate!)) - \(dateFormatter.string(from: endDate!))", for: .normal)
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/AirbnbDatePickerCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePickerCell.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 23/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbDatePickerCell: BaseCell {
12 |
13 | var type: AirbnbDatePickerCellType! = []
14 |
15 | var dateLabel: UILabel = {
16 | let label = UILabel()
17 | label.translatesAutoresizingMaskIntoConstraints = false
18 | label.textAlignment = .center
19 | label.font = UIFont.boldSystemFont(ofSize: 15)
20 | label.textColor = UIColor.white
21 | return label
22 | }()
23 |
24 | var highlightView: UIView = {
25 | let view = UIView()
26 | view.translatesAutoresizingMaskIntoConstraints = false
27 | view.backgroundColor = UIColor.clear
28 | return view
29 | }()
30 |
31 | override func setupViews() {
32 | super.setupViews()
33 |
34 | addSubview(dateLabel)
35 |
36 | dateLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
37 | dateLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
38 | dateLabel.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
39 | dateLabel.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
40 |
41 | addSubview(highlightView)
42 |
43 | highlightView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
44 | highlightView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
45 | highlightView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
46 | highlightView.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
47 | }
48 |
49 | func configureCell() {
50 | if type.contains(.Selected) || type.contains(.SelectedStartDate) || type.contains(.SelectedEndDate) || type.contains(.InBetweenDate) {
51 |
52 | dateLabel.layer.cornerRadius = 0
53 | dateLabel.layer.borderColor = UIColor.white.cgColor
54 | dateLabel.layer.borderWidth = 1
55 | dateLabel.layer.backgroundColor = UIColor.white.cgColor
56 | dateLabel.layer.mask = nil
57 | dateLabel.textColor = Theme.SECONDARY_COLOR
58 |
59 | if type.contains(.SelectedStartDate) {
60 | let side = frame.size.width / 2
61 | let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width: side, height: side))
62 | let shape = CAShapeLayer()
63 | shape.path = maskPath.cgPath
64 | dateLabel.layer.mask = shape
65 |
66 | } else if type.contains(.SelectedEndDate) {
67 | let side = frame.size.width / 2
68 | let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize(width: side, height: side))
69 | let shape = CAShapeLayer()
70 | shape.path = maskPath.cgPath
71 | dateLabel.layer.mask = shape
72 |
73 | } else if !type.contains(.InBetweenDate) {
74 | dateLabel.layer.cornerRadius = frame.size.width / 2
75 | }
76 |
77 | } else if type.contains(.PastDate) {
78 |
79 | dateLabel.layer.cornerRadius = 0
80 | dateLabel.layer.borderColor = UIColor.clear.cgColor
81 | dateLabel.layer.borderWidth = 0
82 | dateLabel.layer.backgroundColor = UIColor.clear.cgColor
83 | dateLabel.layer.mask = nil
84 | dateLabel.textColor = Theme.SECONDARY_COLOR
85 |
86 | } else if type.contains(.Today) {
87 |
88 | dateLabel.layer.cornerRadius = self.frame.size.width / 2
89 | dateLabel.layer.borderColor = Theme.SECONDARY_COLOR.cgColor
90 | dateLabel.layer.borderWidth = 1
91 | dateLabel.layer.backgroundColor = UIColor.clear.cgColor
92 | dateLabel.layer.mask = nil
93 | dateLabel.textColor = UIColor.white
94 |
95 | } else {
96 |
97 | dateLabel.layer.cornerRadius = 0
98 | dateLabel.layer.borderColor = UIColor.clear.cgColor
99 | dateLabel.layer.borderWidth = 0
100 | dateLabel.layer.backgroundColor = UIColor.clear.cgColor
101 | dateLabel.layer.mask = nil
102 | dateLabel.textColor = UIColor.white
103 |
104 | }
105 |
106 |
107 | if type.contains(.Highlighted) {
108 | highlightView.backgroundColor = UIColor(red: 200 / 255, green: 200 / 255, blue: 200 / 255, alpha: 0.6)
109 | highlightView.layer.cornerRadius = frame.size.width / 2
110 | } else {
111 | highlightView.backgroundColor = UIColor.clear
112 | }
113 | }
114 | }
115 |
116 | struct AirbnbDatePickerCellType: OptionSet {
117 | let rawValue: Int
118 |
119 | static let Date = AirbnbDatePickerCellType(rawValue: 1 << 0) // has number
120 | static let Empty = AirbnbDatePickerCellType(rawValue: 1 << 1) // has no number
121 | static let PastDate = AirbnbDatePickerCellType(rawValue: 1 << 2) // disabled
122 | static let Today = AirbnbDatePickerCellType(rawValue: 1 << 3) // has circle
123 | static let Selected = AirbnbDatePickerCellType(rawValue: 1 << 4) // has filled circle
124 | static let SelectedStartDate = AirbnbDatePickerCellType(rawValue: 1 << 5) // has half filled circle on the left
125 | static let SelectedEndDate = AirbnbDatePickerCellType(rawValue: 1 << 6) // has half filled circle on the right
126 | static let InBetweenDate = AirbnbDatePickerCellType(rawValue: 1 << 7) // has filled square
127 | static let Highlighted = AirbnbDatePickerCellType(rawValue: 1 << 8) // has
128 | }
129 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/AirbnbDatePickerFlowLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePickerFlowLayout.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 28/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbDatePickerFlowLayout : UICollectionViewFlowLayout {
12 |
13 | let cellSpacing:CGFloat = 0
14 |
15 | override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
16 | if let attributes = super.layoutAttributesForElements(in: rect) {
17 | for (index, attribute) in attributes.enumerated() {
18 | if index == 0 { continue }
19 | let prevLayoutAttributes = attributes[index - 1]
20 | let origin = prevLayoutAttributes.frame.maxX
21 | if origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize.width {
22 | attribute.frame.origin.x = origin + cellSpacing
23 | }
24 | }
25 | return attributes
26 | }
27 | return nil
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/AirbnbDatePickerFooter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePickerFooter.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 24/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol AirbnbDatePickerFooterDelegate {
12 | func didSave()
13 | }
14 |
15 | class AirbnbDatePickerFooter: UIView {
16 |
17 | var delegate: AirbnbDatePickerFooterDelegate?
18 | var isSaveEnabled: Bool? {
19 | didSet {
20 | if let enabled = isSaveEnabled, enabled {
21 | saveButton.isEnabled = true
22 | saveButton.alpha = 1
23 | } else {
24 | saveButton.isEnabled = false
25 | saveButton.alpha = 0.5
26 | }
27 | }
28 | }
29 |
30 | lazy var saveButton: UIButton = {
31 | let btn = UIButton()
32 | btn.translatesAutoresizingMaskIntoConstraints = false
33 | btn.backgroundColor = Theme.SECONDARY_COLOR
34 | btn.setTitleColor(UIColor.white, for: .normal)
35 | btn.setTitle("Save", for: .normal)
36 | btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
37 | btn.addTarget(self, action: #selector(AirbnbDatePickerFooter.handleSave), for: .touchUpInside)
38 | return btn
39 | }()
40 |
41 | override init(frame: CGRect) {
42 | super.init(frame: frame)
43 |
44 | self.backgroundColor = Theme.PRIMARY_COLOR
45 |
46 | addSubview(saveButton)
47 |
48 | saveButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
49 | saveButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
50 | saveButton.heightAnchor.constraint(equalTo: heightAnchor, constant: -20).isActive = true
51 | saveButton.widthAnchor.constraint(equalTo: widthAnchor, constant: -30).isActive = true
52 | }
53 |
54 | required init?(coder aDecoder: NSCoder) {
55 | fatalError("init(coder:) has not been implemented")
56 | }
57 |
58 | @objc func handleSave() {
59 | if let del = delegate {
60 | del.didSave()
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/AirbnbDatePickerMonthHeader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbDatePickerMonthHeader.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 23/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbDatePickerMonthHeader: BaseCell {
12 |
13 | var monthLabel: UILabel = {
14 | let label = UILabel()
15 | label.translatesAutoresizingMaskIntoConstraints = false
16 | label.textColor = UIColor.white
17 | label.font = UIFont.systemFont(ofSize: 24)
18 | return label
19 | }()
20 |
21 | override func setupViews() {
22 | super.setupViews()
23 |
24 | addSubview(monthLabel)
25 |
26 | monthLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 20).isActive = true
27 | monthLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
28 | monthLabel.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
29 | monthLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Calendar-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Calendar-25.png
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Calendar-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Calendar-50.png
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Calendar-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Calendar-75.png
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Calendar.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Calendar-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Calendar-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Calendar-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Delete.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "Delete-75 (1).png",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Delete.imageset/Delete-75 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-datepicker/airbnb-datepicker/Assets.xcassets/Delete.imageset/Delete-75 (1).png
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/BaseCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseCell.swift
3 | // padstaview
4 | //
5 | // Created by Yonas Stephen on 11/10/16.
6 | // Copyright © 2016 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BaseCell: UICollectionViewCell {
12 | override init(frame: CGRect) {
13 | super.init(frame: frame)
14 | setupViews()
15 | }
16 |
17 | required init?(coder aDecoder: NSCoder) {
18 | fatalError("init(coder:) has not been implemented")
19 | }
20 |
21 | func setupViews() {
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Date.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Date.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 24/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Date {
12 | func startOfMonth() -> Date {
13 | return Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
14 | }
15 |
16 | func endOfMonth() -> Date {
17 | return Calendar.current.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth())!
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Theme.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Theme.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 23/2/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class Theme {
12 |
13 | static let PRIMARY_COLOR = UIColor(r: 0, g: 132, b: 137)
14 | static let SECONDARY_COLOR = UIColor(r: 65, g: 171, b: 175)
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/UIColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor.swift
3 | // mychurch-app
4 | //
5 | // Created by Yonas Stephen on 30/6/16.
6 | // Copyright © 2016 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | convenience init(hex: String) {
13 | var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
14 | if (cString.hasPrefix("#")) {
15 | cString = String(cString.suffix(from: cString.startIndex))
16 | }
17 |
18 | if ((cString.count) != 6) {
19 | self.init()
20 | } else {
21 | var rgbValue:UInt32 = 0
22 | Scanner(string: cString).scanHexInt32(&rgbValue)
23 |
24 | self.init(
25 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
26 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
27 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
28 | alpha: CGFloat(1.0)
29 | )
30 | }
31 | }
32 |
33 | convenience init(r: CGFloat, g: CGFloat, b: CGFloat) {
34 | self.init(red: CGFloat(r / 255), green: CGFloat(g / 255), blue: CGFloat(b / 255), alpha: CGFloat(1))
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/Utility.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Utility.swift
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 2/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Utility {
12 |
13 | static var calendar: Calendar {
14 | get {
15 | var c = Calendar.current
16 | c.timeZone = TimeZone(abbreviation: "GMT")!
17 | return c
18 | }
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/frameworks/airbnb-datepicker/airbnb-datepicker/airbnb-datepicker.h:
--------------------------------------------------------------------------------
1 | //
2 | // airbnb-datepicker.h
3 | // airbnb-datepicker
4 | //
5 | // Created by Yonas Stephen on 5/3/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for airbnb-datepicker.
12 | FOUNDATION_EXPORT double airbnb_datepickerVersionNumber;
13 |
14 | //! Project version string for airbnb-datepicker.
15 | FOUNDATION_EXPORT const unsigned char airbnb_datepickerVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/AirbnbOccupantFilter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbOccupantFilter.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 4/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class AirbnbOccupantFilter: UIView {
12 |
13 | public var delegate: UIViewController?
14 |
15 | var adultCount: Int = 1
16 | var childrenCount: Int = 0
17 | var infantCount: Int = 0
18 | var hasPet: Bool = false
19 |
20 | public var occupantInputButton: UIButton = {
21 | let btn = UIButton()
22 | btn.translatesAutoresizingMaskIntoConstraints = false
23 | btn.backgroundColor = Theme.PRIMARY_COLOR
24 | btn.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left
25 | btn.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
26 | btn.adjustsImageWhenHighlighted = false
27 | btn.addTarget(self, action: #selector(AirbnbOccupantFilter.showOccupantFilter), for: .touchUpInside)
28 |
29 | let img = UIImage(named: "Family", in: Bundle(for: AirbnbOccupantFilter.self), compatibleWith: nil)
30 | btn.setImage(img, for: .normal)
31 | btn.imageView?.contentMode = .scaleAspectFit
32 |
33 | btn.setTitle("1 guest", for: .normal)
34 | btn.setTitleColor(UIColor.white, for: .normal)
35 | btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 15)
36 | btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
37 | btn.titleLabel?.lineBreakMode = .byTruncatingTail
38 | return btn
39 | }()
40 |
41 | public override init(frame: CGRect) {
42 | super.init(frame: frame)
43 | setupViews()
44 | }
45 |
46 | public required init?(coder aDecoder: NSCoder) {
47 | fatalError("init(coder:) has not been implemented")
48 | }
49 |
50 | func setupViews() {
51 | addSubview(occupantInputButton)
52 |
53 | occupantInputButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
54 | occupantInputButton.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
55 | occupantInputButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
56 | occupantInputButton.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
57 |
58 | }
59 |
60 | @objc func showOccupantFilter() {
61 | let occupantController = AirbnbOccupantFilterController(adultCount: adultCount, childrenCount: childrenCount, infantCount: infantCount, hasPet: hasPet)
62 | occupantController.delegate = self
63 | let navigationController = UINavigationController(rootViewController: occupantController)
64 | delegate?.present(navigationController, animated: true, completion: nil)
65 | }
66 | }
67 |
68 | extension AirbnbOccupantFilter: AirbnbOccupantFilterControllerDelegate {
69 | func occupantFilterController(_ occupantFilterController: AirbnbOccupantFilterController, didSaveAdult adult: Int, children: Int, infant: Int, pet: Bool) {
70 |
71 | self.adultCount = adult
72 | self.childrenCount = children
73 | self.infantCount = infant
74 | self.hasPet = pet
75 |
76 | let human = adult + children
77 | let infant = "\(infant > 0 ? (infant.description + " infant" + (infant > 1 ? "s" : "")) : "")"
78 | let pet = "\(pet ? "pets" : "")"
79 |
80 | let text = "\(human) guest\(human > 1 ? "s" : "")" + (infant != "" ? ", " + infant : "") + (pet != "" ? ", " + pet : "")
81 | occupantInputButton.setTitle(text, for: .normal)
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/AirbnbSwitch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AirbnbSwitch.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 5/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AirbnbSwitch: UIView {
12 |
13 | var isAnimating: Bool = false
14 | var state: Bool = false {
15 | didSet {
16 | toggleButton.isEnabled = false
17 | layoutIfNeeded()
18 | UIView.setAnimationCurve(.easeInOut)
19 | UIView.animate(withDuration: 0.2, animations: {
20 | self.toggleButtonLeftConstraint?.isActive = !self.state
21 | self.toggleButtonRightConstraint?.isActive = self.state
22 | self.toggleButton.setImage(self.state ? self.onImage : self.offImage, for: .normal)
23 |
24 | self.layoutIfNeeded()
25 | }, completion: { success in
26 | self.toggleButton.isEnabled = true
27 | })
28 | }
29 | }
30 |
31 | var caption: String? {
32 | didSet {
33 | captionLabel.text = caption
34 | }
35 | }
36 |
37 | var subCaption: String? {
38 | didSet {
39 | subCaptionLabel.text = subCaption
40 | }
41 | }
42 |
43 | var toggleButtonLeftConstraint: NSLayoutConstraint?
44 | var toggleButtonRightConstraint: NSLayoutConstraint?
45 |
46 | var offImage: UIImage = {
47 | var img = UIImage(named: "Delete", in: Bundle(for: AirbnbOccupantFilter.self), compatibleWith: nil)
48 | img = img?.tint(with: Theme.PRIMARY_COLOR)
49 | return img!
50 | }()
51 |
52 | var onImage: UIImage = {
53 | var img = UIImage(named: "Checkmark", in: Bundle(for: AirbnbOccupantFilter.self), compatibleWith: nil)
54 | img = img?.tint(with: Theme.PRIMARY_COLOR)
55 | return img!
56 | }()
57 |
58 | var switchContainer: UIView = {
59 | let view = UIView()
60 | view.translatesAutoresizingMaskIntoConstraints = false
61 |
62 | view.layer.borderColor = UIColor.white.cgColor
63 | view.layer.borderWidth = 1
64 | view.layer.cornerRadius = 15
65 | return view
66 | }()
67 |
68 | lazy var toggleButton: UIButton = {
69 | let button = UIButton()
70 | button.translatesAutoresizingMaskIntoConstraints = false
71 | button.setImage(self.offImage, for: .normal)
72 | button.imageEdgeInsets = UIEdgeInsets(top: 7, left: 7, bottom: 7, right: 7)
73 | button.backgroundColor = UIColor.white
74 | button.addTarget(self, action: #selector(AirbnbSwitch.toggle), for: .touchUpInside)
75 | button.adjustsImageWhenHighlighted = false
76 |
77 | button.layer.borderColor = UIColor.white.cgColor
78 | button.layer.borderWidth = 1
79 | button.layer.cornerRadius = 15
80 | return button
81 | }()
82 |
83 | var captionLabel: UILabel = {
84 | let view = UILabel()
85 | view.translatesAutoresizingMaskIntoConstraints = false
86 | view.font = UIFont.boldSystemFont(ofSize: 22)
87 | view.textColor = UIColor.white
88 | return view
89 | }()
90 |
91 | var subCaptionLabel: UILabel = {
92 | let view = UILabel()
93 | view.translatesAutoresizingMaskIntoConstraints = false
94 | view.font = UIFont.systemFont(ofSize: 15)
95 | view.textColor = UIColor.white
96 | return view
97 | }()
98 |
99 | override init(frame: CGRect) {
100 | super.init(frame: frame)
101 |
102 | setupViews()
103 | }
104 |
105 | override func layoutSubviews() {
106 | super.layoutSubviews()
107 |
108 | }
109 |
110 | required init?(coder aDecoder: NSCoder) {
111 | fatalError("init(coder:) has not been implemented")
112 | }
113 |
114 | func setupViews() {
115 | addSubview(switchContainer)
116 |
117 | switchContainer.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
118 | switchContainer.widthAnchor.constraint(equalToConstant: 40).isActive = true
119 | switchContainer.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
120 | switchContainer.heightAnchor.constraint(equalToConstant: 30).isActive = true
121 |
122 | switchContainer.addSubview(toggleButton)
123 |
124 | toggleButtonLeftConstraint = toggleButton.leftAnchor.constraint(equalTo: switchContainer.leftAnchor)
125 | toggleButtonLeftConstraint?.isActive = true
126 | toggleButtonRightConstraint = toggleButton.rightAnchor.constraint(equalTo: switchContainer.rightAnchor)
127 | toggleButton.widthAnchor.constraint(equalToConstant: 30).isActive = true
128 | toggleButton.centerYAnchor.constraint(equalTo: switchContainer.centerYAnchor).isActive = true
129 | toggleButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
130 |
131 | addSubview(captionLabel)
132 |
133 | captionLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
134 | captionLabel.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 2/3).isActive = true
135 | captionLabel.rightAnchor.constraint(equalTo: switchContainer.leftAnchor).isActive = true
136 | captionLabel.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
137 |
138 | addSubview(subCaptionLabel)
139 |
140 | subCaptionLabel.topAnchor.constraint(equalTo: captionLabel.bottomAnchor).isActive = true
141 | subCaptionLabel.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 1/3).isActive = true
142 | subCaptionLabel.rightAnchor.constraint(equalTo: switchContainer.leftAnchor).isActive = true
143 | subCaptionLabel.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
144 | }
145 |
146 | @objc func toggle() {
147 | state = !state
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "size" : "1024x1024",
46 | "scale" : "1x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-25.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-50.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Checkmark-75.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Checkmark.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Checkmark-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Checkmark-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Checkmark-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Delete-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Delete-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Delete-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-25.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-50.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Delete.imageset/Delete-75.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Family Man Woman-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Family Man Woman-50.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Family Man Woman-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-25.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-50.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Family.imageset/Family Man Woman-75.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Minus-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Minus-48.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Minus-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-25.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-48.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Minus.imageset/Minus-75.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Plus Math-25.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Plus Math-48.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Plus Math-75.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-25.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-48.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonasstephen/swift-of-airbnb/4d4be9428a7257250c97bf06c706590cd2c924f2/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Assets.xcassets/Plus.imageset/Plus Math-75.png
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/Theme.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Theme.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 4/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class Theme {
12 |
13 | static let PRIMARY_COLOR = UIColor(r: 0, g: 132, b: 137)
14 | static let SECONDARY_COLOR = UIColor(r: 65, g: 171, b: 175)
15 |
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/UIColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 4/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | convenience init(hex: String) {
13 | var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
14 | if (cString.hasPrefix("#")) {
15 | cString = String(cString.suffix(from: cString.startIndex))
16 | }
17 |
18 | if ((cString.count) != 6) {
19 | self.init()
20 | } else {
21 | var rgbValue:UInt32 = 0
22 | Scanner(string: cString).scanHexInt32(&rgbValue)
23 |
24 | self.init(
25 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
26 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
27 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
28 | alpha: CGFloat(1.0)
29 | )
30 | }
31 | }
32 |
33 | convenience init(r: CGFloat, g: CGFloat, b: CGFloat) {
34 | self.init(red: CGFloat(r / 255), green: CGFloat(g / 255), blue: CGFloat(b / 255), alpha: CGFloat(1))
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/UIImage.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage.swift
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 5/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIImage {
12 | func tint(with color: UIColor) -> UIImage {
13 | var image = withRenderingMode(.alwaysTemplate)
14 | UIGraphicsBeginImageContextWithOptions(size, false, scale)
15 | color.set()
16 |
17 | image.draw(in: CGRect(origin: .zero, size: size))
18 | image = UIGraphicsGetImageFromCurrentImageContext()!
19 | UIGraphicsEndImageContext()
20 | return image
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/frameworks/airbnb-occupant-filter/airbnb-occupant-filter/airbnb-occupant-filter.h:
--------------------------------------------------------------------------------
1 | //
2 | // airbnb-occupant-filter.h
3 | // airbnb-occupant-filter
4 | //
5 | // Created by Yonas Stephen on 6/4/17.
6 | // Copyright © 2017 Yonas Stephen. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for airbnb-occupant-filter.
12 | FOUNDATION_EXPORT double airbnb_occupant_filterVersionNumber;
13 |
14 | //! Project version string for airbnb-occupant-filter.
15 | FOUNDATION_EXPORT const unsigned char airbnb_occupant_filterVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # Swift of Airbnb
5 |
6 | This is a self-taught project of learning Swift inspired by [Sam Lu's 100 Days of Swift] and [Allen Wong's 30 Days of Swift]. Trying to take the learning progress further by making some of Airbnb's screens, which in my opinion is one of the most beautifully-designed iOS App. Kudos to Airbnb for setting such high standard in iOS Development.
7 |
8 | # Projects
9 |
10 | ### Project 1 - Occupant Filter
11 |
12 | 
13 |
14 | Things I learn:
15 | - Custom counter control AirbnbCounter
16 | - Custom UISwitch control AirbnbSwitch which is basically an image UIButton that animates from left to right when the value toggled
17 |
18 | ### Project 2 - Date Picker
19 |
20 | 
21 |
22 | Things I learn:
23 | - All kinds of things with UICollectionView (didSelect, didHighlight, shouldSelect, shouldHighlight, de/selecting cells programatically, etc.)
24 | - One issue that made me stuck for days was there was tiny pixel gap between date cells that I couldn't remove. I posted the solution here: http://stackoverflow.com/a/42574952/2105910
25 |
26 | ### Project 3 - Main Screen
27 |
28 | 
29 |
30 | Things I learn:
31 | - How to make iOS Frameworks (using the previous 2 components in this screen)
32 | - UITableView header animation (view position & alpha change as user scrolls)
33 | - Custom page tab navigation with underline border that animates to selected page (For You, Homes, Experience, Places)
34 | - Nested UICollectionView inside UITableView
35 |
36 | ### Project 4 - Custom Page Transition
37 |
38 | 
39 |
40 | Things I learn:
41 | - A lot from here: https://www.raywenderlich.com/110536/custom-uiviewcontroller-transitions and here: http://blog.matthewcheok.com/design-teardown-preview-expanding-cells/
42 | - How to slice and snapshot views to animate transition on present and dismiss
43 | - New AirbnbReview component
44 |
45 | # Coming Soon
46 |
47 | This is an ongoing project and a lot of things already planned!
48 |
49 | - ~~Page transition animation on selecting home item~~
50 | - The map view! (that all other booking apps copy :D)
51 | - Home detail screen
52 | - My trips screen
53 | - or you let me know what you wanna see!
54 |
55 | # Resources
56 | [Michigan Labs]
57 |
58 | [Raywenderlich]
59 |
60 | [Pexels]
61 |
62 | [Icons 8]
63 |
64 | [Let's Build That App]
65 |
66 | # License
67 |
68 | Swift of Airbnb is licensed under MIT License
69 |
70 | [//]: # (These are reference links used in the body of this note and get stripped out when the markdown processor does its job. There is no need to format nicely because it shouldn't be seen. Thanks SO - http://stackoverflow.com/questions/4823468/store-comments-in-markdown-syntax)
71 |
72 | [Allen Wong's 30 Days of Swift]:
73 | [Sam Lu's 100 Days of Swift]:
74 | [Michigan Labs]:
75 | [Raywenderlich]:
76 | [Pexels]:
77 | [Icons 8]:
78 | [Let's Build That App]:
79 |
80 |
--------------------------------------------------------------------------------