-
Notifications
You must be signed in to change notification settings - Fork 343
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
WIP: Replacing the calendar after DayView initializing #294
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ public protocol DayViewStateUpdating: AnyObject { | |
|
||
public final class DayViewState { | ||
public private(set) var calendar: Calendar | ||
// willSet {} // TODO: I think this needs to be implemented, cause timezone can change without creating a new state object | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest ensuring that changing the timezone will always create a new state object There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest that changing TimeZone (or Calendar, in this case) should always trigger creation of a new |
||
public private(set) var selectedDate: Date | ||
private var clients = [DayViewStateUpdating]() | ||
|
||
|
@@ -17,6 +18,7 @@ public final class DayViewState { | |
|
||
public func move(to date: Date) { | ||
let date = date.dateOnly(calendar: calendar) | ||
// if (date == selectedDate) { return } // TODO: If necessary? Just trying to make sure that willMoveTo not be called if we are already on this page | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, adding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest against including such statements. If Returning early if date hasn't changed would only complicate debugging. I'm for very simple |
||
notify(clients: clients, moveTo: date) | ||
selectedDate = date | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,4 +14,12 @@ extension Date { | |
let returnValue = calendar.date(from: newComponents) | ||
return returnValue! | ||
} | ||
|
||
/// Cuts off the time, leaving the beginning of the day for the new time zone | ||
func dateOnly(calendar: Calendar, oldCalendar: Calendar) -> Date { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest renaming to something like:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest renaming to something akin to |
||
var newDate = self.dateOnly(calendar: oldCalendar) | ||
let diff = oldCalendar.timeZone.secondsFromGMT() - calendar.timeZone.secondsFromGMT() | ||
newDate.addTimeInterval(TimeInterval(diff)) | ||
return newDate | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,13 @@ import DateToolsSwift | |
|
||
public final class DayHeaderView: UIView, DaySelectorDelegate, DayViewStateUpdating, UIPageViewControllerDataSource, UIPageViewControllerDelegate { | ||
public private(set) var daysInWeek = 7 | ||
public let calendar: Calendar | ||
public var calendar: Calendar { | ||
didSet { | ||
daySymbolsView.calendar = calendar | ||
swipeLabelView.calendar = calendar | ||
configure() // TODO: Should I do it that way or better just to set a new vc without adding subview (like in state#didSet)? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, the proper solution is to refactor the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest refactoring the |
||
} | ||
} | ||
|
||
private var style = DayHeaderStyle() | ||
private var currentSizeClass = UIUserInterfaceSizeClass.compact | ||
|
@@ -16,6 +22,14 @@ public final class DayHeaderView: UIView, DaySelectorDelegate, DayViewStateUpdat | |
didSet { | ||
state?.subscribe(client: self) | ||
swipeLabelView.state = state | ||
|
||
// Fixes the "jump" of the pager from today to the selected date. This is noticeable | ||
// when we are on a date outside of today's week, and try to change the time zone. | ||
let previousSelectedDate = state!.selectedDate // day selected before timezone change | ||
let vc = makeSelectorController(startDate: beginningOfWeek(previousSelectedDate)) | ||
vc.selectedDate = previousSelectedDate | ||
currentWeekdayIndex = vc.selectedIndex | ||
pagingViewController.setViewControllers([vc], direction: .forward, animated: false, completion: nil) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, any glitches during the configuration process are OK, as it should happen "behind the scenes", i.e. when the DayViewController is not displayed or obscured by another view. |
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,15 @@ import UIKit | |
|
||
public final class DaySymbolsView: UIView { | ||
public private(set) var daysInWeek = 7 | ||
private var calendar = Calendar.autoupdatingCurrent | ||
public var calendar = Calendar.autoupdatingCurrent { | ||
didSet { | ||
// TODO: I honestly don't know if I should be doing this. Changes to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, it's a good practice. The API suggest the possibility of changing the Calendar, what if e.g. 1st day of week has changed? In that case reconfiguration would be necessary. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's correct approach. API allows changing of the |
||
// the timezone should not affect the displayed days of the week, | ||
// however, just in case, I am reconfiguring this view | ||
configure() | ||
setNeedsLayout() | ||
} | ||
} | ||
private var labels = [UILabel]() | ||
private var style: DaySymbolsStyle = DaySymbolsStyle() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,13 @@ public final class SwipeLabelView: UIView, DayViewStateUpdating { | |
case Backward | ||
} | ||
|
||
public private(set) var calendar = Calendar.autoupdatingCurrent | ||
public var calendar = Calendar.autoupdatingCurrent { | ||
didSet { | ||
// I doubt that someone will use this view without a state, but | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's good to keep CK modular, as there are already use-cases when a few CK modules are used on their own or configured by the developer in a non-standard way. So, it's a great idea to keep the modularity going. |
||
// I consider it necessary to update text label for such a situation | ||
updateLabelText() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's correct approach. |
||
} | ||
} | ||
public weak var state: DayViewState? { | ||
willSet(newValue) { | ||
state?.unsubscribe(client: self) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,17 @@ public final class TimelinePagerView: UIView, UIGestureRecognizerDelegate, UIScr | |
public weak var dataSource: EventDataSource? | ||
public weak var delegate: TimelinePagerViewDelegate? | ||
|
||
public private(set) var calendar: Calendar = Calendar.autoupdatingCurrent | ||
public var calendar: Calendar = Calendar.autoupdatingCurrent { | ||
didSet { | ||
// changing timezone in loaded pages | ||
pagingViewController.children.forEach { | ||
let vc = $0 as! TimelineContainerController | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think it's worth doing it? After all, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be simpler to modify, e.g. to use a protocol instead of a concrete class I'd go for a safe solution without a crash here, although I agree that it's highly unlikely that a crash will happen. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My main suggestion for this pull request would be instead of modifying the existing It would be much simpler programmatically, as the newly created controllers would have a clean state, instead of a modified one, which would make it easier to reason about... ... And would remove the need to use hacks such as in |
||
let oldCalendar = vc.timeline.calendar | ||
vc.timeline.date = vc.timeline.date.dateOnly(calendar: calendar, oldCalendar: oldCalendar) | ||
vc.timeline.calendar = calendar | ||
} | ||
} | ||
} | ||
|
||
public var timelineScrollOffset: CGPoint { | ||
// Any view is fine as they are all synchronized | ||
|
@@ -173,7 +183,11 @@ public final class TimelinePagerView: UIView, UIGestureRecognizerDelegate, UIScr | |
|
||
private func updateTimeline(_ timeline: TimelineView) { | ||
guard let dataSource = dataSource else {return} | ||
let date = timeline.date.dateOnly(calendar: calendar) | ||
// I don't know under what circumstances, but I know for sure that | ||
// a situation is possible when these calendars have different time | ||
// zones. It is in this case that the call below will prevent a bug | ||
// that leads to "jumps" after days when you swipe to the left | ||
let date = timeline.date.dateOnly(calendar: calendar, oldCalendar: timeline.calendar) | ||
let events = dataSource.eventsForDate(date) | ||
let day = TimePeriod(beginning: date, | ||
chunk: TimeChunk.dateComponents(days: 1)) | ||
|
@@ -437,7 +451,7 @@ public final class TimelinePagerView: UIView, UIGestureRecognizerDelegate, UIScr | |
// MARK: UIPageViewControllerDataSource | ||
|
||
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { | ||
guard let containerController = viewController as? TimelineContainerController else {return nil} | ||
guard let containerController = viewController as? TimelineContainerController else {return nil} | ||
let previousDate = containerController.timeline.date.add(TimeChunk.dateComponents(days: -1), calendar: calendar) | ||
let vc = configureTimelineController(date: previousDate) | ||
let offset = (pageViewController.viewControllers?.first as? TimelineContainerController)?.container.contentOffset | ||
|
@@ -446,7 +460,7 @@ public final class TimelinePagerView: UIView, UIGestureRecognizerDelegate, UIScr | |
} | ||
|
||
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { | ||
guard let containerController = viewController as? TimelineContainerController else {return nil} | ||
guard let containerController = viewController as? TimelineContainerController else {return nil} | ||
let nextDate = containerController.timeline.date.add(TimeChunk.dateComponents(days: 1), calendar: calendar) | ||
let vc = configureTimelineController(date: nextDate) | ||
let offset = (pageViewController.viewControllers?.first as? TimelineContainerController)?.container.contentOffset | ||
|
@@ -459,7 +473,19 @@ public final class TimelinePagerView: UIView, UIGestureRecognizerDelegate, UIScr | |
public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { | ||
guard completed else {return} | ||
if let timelineContainerController = pageViewController.viewControllers?.first as? TimelineContainerController { | ||
let selectedDate = timelineContainerController.timeline.date | ||
// Unfortunately, I cannot explain this change in detail. I fiddled | ||
// with a bug in which some days were skipped when swiping, completely | ||
// desperate and wrote this. To my surprise, this solved the problem. | ||
// I'll do some research on the reasons later. | ||
|
||
// Попытка пофиксить сбой хедера с перескоком через число | ||
var selectedDate = timelineContainerController.timeline.date | ||
selectedDate = selectedDate.dateOnly(calendar: self.state!.calendar, oldCalendar: timelineContainerController.container.timeline.calendar) | ||
|
||
// попытка пофиксить баг с уменьшением и свайпом | ||
timelineContainerController.timeline.date = selectedDate // Я хз как и какие последствия оно имеет, но это сработало | ||
timelineContainerController.timeline.calendar = self.state!.calendar | ||
|
||
delegate?.timelinePager(timelinePager: self, willMoveTo: selectedDate) | ||
state?.client(client: self, didMoveTo: selectedDate) | ||
scrollToFirstEventIfNeeded() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.... To send the new date to all the clients?