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

[NAT-269] [iOS] react-native-date-picker extend with new callback onStateChange #831

Closed
wants to merge 2 commits into from
Closed
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
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,22 @@ buck-out/
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

## Build generated
DerivedData/
Expand Down
32 changes: 32 additions & 0 deletions ios/DataManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// DataManager.swift
// FlipDatePicker
//
// Created by Halina Smolskaya on 10/06/2024.
//

import Foundation

public struct DataManager {
let collections: [DataSource]

public var numberOfComponents: Int {
collections.count
}

public func getValueInComponentForRow(component: Int, row: Int) -> String? {
collections[safe: component]?.getValueForRow(row)
}

public func getNumberOfRowsInComponent(_ component: Int) -> Int {
collections[safe: component]?.count ?? 0
}

public var components: Set<Calendar.Component> {
Set(collections.compactMap { $0.component == .nanosecond ? nil : $0.component })
}

public func componentIndex(component: Calendar.Component) -> Int? {
collections.firstIndex { $0.component == component }
}
}
39 changes: 39 additions & 0 deletions ios/DataSources/ComponentDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// ComponentDataSource.swift
// FlipDatePicker
//
// Created by Halina Smolskaya on 10/06/2024.
//

import Foundation

public struct ComponentDataSource: DataSource {
let data: [String]
let component: Calendar.Component

var count: Int {
data.count
}

var middleRow: Int {
0
}

public init(data: [String], component: Calendar.Component) {
self.data = data
self.component = component
}

func getValueForRow(_ row: Int) -> String? {
data[safe: row]
}

func getRowForValue(_ value: String?) -> Int? {
guard let value else { return nil }
return data.firstIndex(of: value)
}

func getOriginalRow(_ row: Int) -> Int {
row
}
}
41 changes: 41 additions & 0 deletions ios/DataSources/ComponentInfinityDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// ComponentInfinityDataSource.swift
// FlipDatePicker
//
// Created by Halina Smolskaya on 10/06/2024.
//

import Foundation

let loopingMargin: Int = 1000

public struct ComponentInfinityDataSource: DataSource {
let data: [String]
let component: Calendar.Component

var count: Int {
data.count * loopingMargin
}

var middleRow: Int {
(loopingMargin / 2) * data.count
}

public init(data: [String], component: Calendar.Component) {
self.data = data
self.component = component
}

func getValueForRow(_ row: Int) -> String? {
data[safe: row % data.count]
}

func getRowForValue(_ value: String?) -> Int? {
guard let value, let index = data.firstIndex(of: value) else { return nil }
return middleRow + index
}

func getOriginalRow(_ row: Int) -> Int {
row % data.count
}
}
19 changes: 19 additions & 0 deletions ios/DataSources/DataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// DataSource.swift
// FlipDatePicker
//
// Created by Halina Smolskaya on 10/06/2024.
//

import Foundation

protocol DataSource {
var data: [String] { get }
var component: Calendar.Component { get }
var count: Int { get }
var middleRow: Int { get }

func getValueForRow(_ row: Int) -> String?
func getRowForValue(_ value: String?) -> Int?
func getOriginalRow(_ row: Int) -> Int
}
105 changes: 105 additions & 0 deletions ios/DatePicker+DataManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//
// DatePicker+DataManager.swift
// FlipDatePicker
//
// Created by Halina Smolskaya on 11/06/2024.
//

import Foundation

extension DatePicker {
public func createDataManager() -> DataManager {
switch datePickerMode {
case .time:
createTimeModeManager()
case .date:
createDateModeManager()
case .dateAndTime:
createDateAndTimeModeManager()
case .countDownTimer:
createDateModeManager()
}
}

private func createDateModeManager() -> DataManager {
let months = ComponentInfinityDataSource(data: calendar.monthSymbols, component: .month)
let days = ComponentInfinityDataSource(data: (1 ... 31).map { "\($0)" }, component: .day)
let years = ComponentDataSource(data: (1800 ... 2200).map { "\($0)" }, component: .year)

return DataManager(collections: [months, days, years])
}

private func createTimeModeManager() -> DataManager {
let hours = ComponentInfinityDataSource(data: generateHours(), component: .hour)
let minutes = ComponentInfinityDataSource(
data: stride(from: 0, to: 60, by: minuteInterval).map { String(format: "%02d", $0) },
component: .minute
)
let nanoseconds: DataSource? = is24HourFormat()
? nil
: ComponentDataSource(
data: [calendar.amSymbol, calendar.pmSymbol],
component: .nanosecond
)

return DataManager(collections: [hours, minutes, nanoseconds].compactMap { $0 })
}

private func createDateAndTimeModeManager() -> DataManager {
let days = ComponentDataSource(data: generateAllDaysInYear(), component: .day)
let hours = ComponentInfinityDataSource(data: generateHours(), component: .hour)
let minutes = ComponentInfinityDataSource(
data: stride(from: 0, to: 60, by: minuteInterval).map { String(format: "%02d", $0) },
component: .minute
)
let nanoseconds: DataSource? = is24HourFormat()
? nil
: ComponentDataSource(
data: [calendar.amSymbol, calendar.pmSymbol],
component: .nanosecond
)

return DataManager(collections: [days, hours, minutes, nanoseconds].compactMap { $0 })
}

private func createCountDownTimer() -> DataManager {
let hours = ComponentDataSource(data: (0 ... 23).map { String(format: "%02d", $0) }, component: .hour)
let minutes = ComponentInfinityDataSource(
data: stride(from: 0, to: 60, by: minuteInterval).map { String(format: "%02d", $0) },
component: .minute
)

return DataManager(collections: [hours, minutes])
}

private func generateAllDaysInYear() -> [String] {
let year = calendar.component(.year, from: selectedDate ?? Date())
let dateComponents = DateComponents(year: year, month: 1, day: 1)
guard let startDate = calendar.date(from: dateComponents),
let range = calendar.range(of: .day, in: .year, for: startDate)
else { return [] }

let dateFormatter = DateFormatter()
dateFormatter.locale = locale
dateFormatter.dateFormat = "EEE MMM d"

var dates: [String] = []
for day in range {
if let date = calendar.date(byAdding: .day, value: day - 1, to: startDate) {
let formattedDate = dateFormatter.string(from: date)
dates.append(formattedDate)
}
}
return dates
}

private func generateHours() -> [String] {
var hoursArray: [String] = []
for value in 0 ..< 24 {
let hour = is24HourFormat() ? value : (value % 12 == 0 ? 12 : value % 12)
let hourString = is24HourFormat() ? String(format: "%02d", hour) : "\(hour)"
hoursArray.append(hourString)
}
return hoursArray
}
}
18 changes: 18 additions & 0 deletions ios/DatePicker+UIPickerViewDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// DatePicker+UIPickerViewDataSource.swift
// FlipDatePicker
//
// Created by Halina Smolskaya on 07/06/2024.
//

import UIKit

extension DatePicker: UIPickerViewDataSource {
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
dataManager.numberOfComponents
}

public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
dataManager.getNumberOfRowsInComponent(component)
}
}
Loading
Loading