Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SwiftUI Support #54

Merged
merged 4 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Example/FastisExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
1A3E7A5E2A40901600434229 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1A3E7A602A40901600434229 /* Localizable.strings */; };
1AB955832BA31F4200235243 /* HostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB955822BA31F4200235243 /* HostingController.swift */; };
1AB955852BA31F5500235243 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB955842BA31F5500235243 /* MainView.swift */; };
F381AF9628B8C7190046383A /* Fastis in Frameworks */ = {isa = PBXBuildFile; productRef = F381AF9528B8C7190046383A /* Fastis */; };
F3FCEE47244780FE000F966E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3FCEE46244780FE000F966E /* AppDelegate.swift */; };
F3FCEE4B244780FE000F966E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3FCEE4A244780FE000F966E /* ViewController.swift */; };
Expand All @@ -19,6 +21,8 @@
1A3E7A5F2A40901600434229 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
1A3E7A612A40902000434229 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = "<group>"; };
1A3E7A622A409B3A00434229 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
1AB955822BA31F4200235243 /* HostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingController.swift; sourceTree = "<group>"; };
1AB955842BA31F5500235243 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
CB137E4877EBDC6E87A77A4B /* Pods_FastisExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FastisExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F31CFB6B28B8C32D00364F6A /* Fastis */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Fastis; path = ..; sourceTree = "<group>"; };
F3FCEE43244780FE000F966E /* FastisExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FastisExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -80,6 +84,8 @@
children = (
F3FCEE46244780FE000F966E /* AppDelegate.swift */,
F3FCEE4A244780FE000F966E /* ViewController.swift */,
1AB955822BA31F4200235243 /* HostingController.swift */,
1AB955842BA31F5500235243 /* MainView.swift */,
F3FCEE4F24478100000F966E /* Assets.xcassets */,
F3FCEE5124478100000F966E /* LaunchScreen.storyboard */,
F3FCEE5424478100000F966E /* Info.plist */,
Expand Down Expand Up @@ -164,6 +170,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1AB955832BA31F4200235243 /* HostingController.swift in Sources */,
1AB955852BA31F5500235243 /* MainView.swift in Sources */,
F3FCEE4B244780FE000F966E /* ViewController.swift in Sources */,
F3FCEE47244780FE000F966E /* AppDelegate.swift in Sources */,
);
Expand Down
26 changes: 26 additions & 0 deletions Example/Source/HostingController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// HostingController.swift
// FastisExample
//
// Created by Yriy Devyataev on 13.03.2024.
// Copyright © 2024 RetailDriver LLC. All rights reserved.
//

import SwiftUI

/**
The view is used to display SwiftUI view in the UIKit project
*/

class HostingController: UIHostingController<MainView> {

init() {
super.init(rootView: MainView())
}

@available(*, unavailable)
dynamic required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

}
91 changes: 91 additions & 0 deletions Example/Source/MainView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// CalendarView.swift
// FastisExample
//
// Created by Yriy Devyataev on 13.03.2024.
// Copyright © 2024 RetailDriver LLC. All rights reserved.
//

import Fastis
import Foundation
import SwiftUI
import UIKit

/**
View is used as a possible example of a SwiftUI project.
*/
struct MainView: View {

private let calendar: Calendar = .current

@State private var showSingleCalendar = false
@State private var showRangeCalendar = false
@State private var currentValueText = "Choose a date"

@State var currentValue: FastisValue? {
didSet {
if let rangeValue = self.currentValue as? FastisRange {
self.currentValueText = self.dateFormatter.string(from: rangeValue.fromDate) + " - " + self.dateFormatter
.string(from: rangeValue.toDate)
} else if let date = self.currentValue as? Date {
self.currentValueText = self.dateFormatter.string(from: date)
} else {
self.currentValueText = "Choose a date"
}
}
}

private var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
formatter.calendar = self.calendar
return formatter
}

var body: some View {
VStack(spacing: 32, content: {
Text(self.currentValueText)
VStack(alignment: .center, spacing: 16, content: {
Button("Choose range of dates") {
self.showRangeCalendar.toggle()
}
Button("Choose single date") {
self.showSingleCalendar.toggle()
}
})
})
.navigationTitle("SwiftUI presentation")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.sheet(isPresented: self.$showRangeCalendar) {
FastisView(mode: .range) { action in
if case .done(let newValue) = action {
self.currentValue = newValue
}
}
.title("Choose range")
.initialValue(self.currentValue as? FastisRange)
.minimumDate(self.calendar.date(byAdding: .month, value: -2, to: Date()))
.maximumDate(self.calendar.date(byAdding: .month, value: 3, to: Date()))
.allowToChooseNilDate(true)
.allowDateRangeChanges(false)
.shortcuts([.lastWeek, .lastMonth])
.selectMonthOnHeaderTap(true)
.ignoresSafeArea()
}
.sheet(isPresented: self.$showSingleCalendar) {
FastisView(mode: .single) { action in
if case .done(let newValue) = action {
self.currentValue = newValue
}
}
.title("Choose date")
.initialValue(self.currentValue as? Date)
.minimumDate(self.calendar.date(byAdding: .month, value: -2, to: Date()))
.maximumDate(Date())
.allowToChooseNilDate(true)
.shortcuts([.yesterday, .today, .tomorrow])
.closeOnSelectionImmediately(true)
.ignoresSafeArea()
}
}
}
26 changes: 21 additions & 5 deletions Example/Source/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,17 @@ class ViewController: UIViewController {
return button
}()

private lazy var chooseSingleButtonWithCustomCalendar: UIButton = {
private lazy var chooseRangeButtonWithCustomCalendar: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Choose single date with custom calendar", for: .normal)
button.addTarget(self, action: #selector(self.chooseSingleDateWithCustomCalendar), for: .touchUpInside)
button.setTitle("Choose range of dates with custom calendar", for: .normal)
button.addTarget(self, action: #selector(self.chooseRangeWithCustomCalendar), for: .touchUpInside)
return button
}()

private lazy var chooseWithSwiftUI: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Choose with SwiftUI", for: .normal)
button.addTarget(self, action: #selector(self.swiftUIPresentation), for: .touchUpInside)
return button
}()

Expand Down Expand Up @@ -91,7 +98,8 @@ class ViewController: UIViewController {
self.containerView.setCustomSpacing(32, after: self.currentDateLabel)
self.containerView.addArrangedSubview(self.chooseRangeButton)
self.containerView.addArrangedSubview(self.chooseSingleButton)
self.containerView.addArrangedSubview(self.chooseSingleButtonWithCustomCalendar)
self.containerView.addArrangedSubview(self.chooseRangeButtonWithCustomCalendar)
self.containerView.addArrangedSubview(self.chooseWithSwiftUI)
self.view.addSubview(self.containerView)
}

Expand Down Expand Up @@ -149,7 +157,7 @@ class ViewController: UIViewController {
}

@objc
private func chooseSingleDateWithCustomCalendar() {
private func chooseRangeWithCustomCalendar() {
var customConfig: FastisConfig = .default
var calendar: Calendar = .init(identifier: .islamicUmmAlQura)
calendar.locale = .autoupdatingCurrent
Expand All @@ -175,4 +183,12 @@ class ViewController: UIViewController {
fastisController.present(above: self)
}

@objc
private func swiftUIPresentation() {
let hostingController = HostingController()
hostingController.modalPresentationStyle = .custom
let navVC = self.parent as? UINavigationController
navVC?.pushViewController(hostingController, animated: true)
}

}
51 changes: 49 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Fastis is a fully customisable UI component for picking dates and ranges created
- [Configuration](#configuration)
- [Shortcuts](#shortcuts)
- [Customization](#customization)
- [SwiftUI](#swiftui)
- [Credits](#credits)
- [License](#license)

Expand Down Expand Up @@ -161,7 +162,6 @@ var maximumDate: Date? = nil
var selectMonthOnHeaderTap: Bool = true
var allowDateRangeChanges: Bool = true
var closeOnSelectionImmediately: Bool = false

```

- `shortcuts`- Shortcuts array. The default value is `[]`. See [Shortcuts](#shortcuts) section
Expand Down Expand Up @@ -226,7 +226,7 @@ To customise a special FastisController instance with custom calendar:

```swift
var customConfig: FastisConfig = .default
var calendar: Calendar = .init(identifier: .islamicUmmAlQura)
var calendar = Calendar(identifier: .islamicUmmAlQura)
calendar.locale = .autoupdatingCurrent
customConfig.calendar = calendar
let fastisController = FastisController(mode: .range, config: customConfig)
Expand All @@ -246,9 +246,56 @@ config.todayCell.circleViewColor = .red

If you don't want to customzie today date cell, just set `config.todayCell = nil` and today cell will use `dayCell` config.

### SwiftUI

The library also contains a SwiftUI wrapper

If you want to get a date range:

```swift
FastisView(mode: .single, dismissHandler: { action in
switch action {
case .done(let resultDate):
print(resultDate) // resultDate is Date
case .cancel:
...
}
})
.title("Choose range")
.initialValue(self.currentValue as? FastisRange)
.minimumDate(Calendar.current.date(byAdding: .month, value: -2, to: Date()))
.maximumDate(Calendar.current.date(byAdding: .month, value: 3, to: Date()))
.allowToChooseNilDate(true)
.allowDateRangeChanges(false)
.shortcuts([.lastWeek, .lastMonth])
.selectMonthOnHeaderTap(true)
```

If you want to get a single date:

```swift
FastisView(mode: .range, dismissHandler: { action in
switch action {
case .done(let resultRange):
print(resultRange) // resultRange is FastisRange
case .cancel:
...
}
})
.title("Choose date")
.initialValue(self.currentValue as? Date)
.minimumDate(Calendar.current.date(byAdding: .month, value: -2, to: Date()))
.maximumDate(Date())
.allowToChooseNilDate(true)
.allowDateRangeChanges(false)
.shortcuts([.yesterday, .today, .tomorrow])
.closeOnSelectionImmediately(true)
```

## Credits

- Ilya Kharlamov ([@ilia3546](https://github.com/ilia3546))
- Uriy Devyataev ([@UriyDevyataev](https://github.com/UriyDevyataev))

## License

Expand Down
Loading