// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "content/browser/date_time_chooser/ios/date_time_chooser_view_controller.h"
#import "base/notreached.h"
#import "content/browser/date_time_chooser/ios/date_time_chooser_util.h"
#import "third_party/blink/public/mojom/choosers/date_time_chooser.mojom.h"
#import "ui/base/ime/text_input_type.h"
const CGFloat kToolBarHeight = 44;
@interface DateTimeChooserViewController ()
// The type to set the date picker mode
@property(nonatomic, assign) ui::TextInputType type;
// Initalized time for the date picker. For TEXT_INPUT_TYPE_MONTH, it is the
// number of month. Otherwise, it's in milliseconds.
@property(nonatomic, assign) NSInteger initTime;
// Updated with the selected date in the date picker
@property(nonatomic, assign) NSDate* selectedDate;
@end
@implementation DateTimeChooserViewController
- (instancetype)initWithConfigs:(DateTimeDialogValuePtr)configs {
if (!(self = [super init])) {
return nil;
}
_delegate = nil;
_type = configs->dialog_type;
_initTime = configs->dialog_value;
// TODO(crbug.com/40274667): Handle other values in `configs` such as minimum
// or maximum.
return self;
}
- (UIDatePicker*)createUIDatePicker {
UIDatePicker* datePicker = [[UIDatePicker alloc] init];
UIDatePickerMode mode = UIDatePickerModeDate;
UIDatePickerStyle style = UIDatePickerStyleAutomatic;
NSDate* initValue;
switch (self.type) {
case ui::TextInputType::TEXT_INPUT_TYPE_DATE:
initValue = [NSDate dateWithTimeIntervalSince1970:self.initTime / 1000];
mode = UIDatePickerModeDate;
style = UIDatePickerStyleInline;
break;
case ui::TextInputType::TEXT_INPUT_TYPE_TIME:
initValue = [NSDate dateWithTimeIntervalSince1970:self.initTime / 1000];
mode = UIDatePickerModeTime;
style = UIDatePickerStyleWheels;
break;
case ui::TextInputType::TEXT_INPUT_TYPE_DATE_TIME:
case ui::TextInputType::TEXT_INPUT_TYPE_DATE_TIME_LOCAL:
initValue = [NSDate dateWithTimeIntervalSince1970:self.initTime / 1000];
mode = UIDatePickerModeDateAndTime;
style = UIDatePickerStyleInline;
break;
case ui::TextInputType::TEXT_INPUT_TYPE_MONTH:
initValue = GetDateFromNumberOfMonths(self.initTime);
mode = UIDatePickerModeDate;
style = UIDatePickerStyleWheels;
break;
case ui::TextInputType::TEXT_INPUT_TYPE_WEEK:
initValue = [NSDate dateWithTimeIntervalSince1970:self.initTime / 1000];
// UIDatePicker doesn't have a mode for the week number. So, it opens
// UIDatePicker with UIDatePickerModeDate and converts the selected
// to the week number.
mode = UIDatePickerModeDate;
style = UIDatePickerStyleInline;
break;
default:
NOTREACHED_IN_MIGRATION() << "Invalid type for a DateTimeChooser.";
break;
}
datePicker.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
datePicker.datePickerMode = mode;
datePicker.preferredDatePickerStyle = style;
[datePicker setDate:initValue animated:FALSE];
[datePicker addTarget:self
action:@selector(datePickerValueChanged:)
forControlEvents:UIControlEventValueChanged];
return datePicker;
}
- (void)cancelButtonTapped {
[[self presentingViewController] dismissViewControllerAnimated:YES
completion:nil];
[self.delegate dateTimeChooser:self
didCloseSuccessfully:FALSE
withDate:self.selectedDate
forType:self.type];
}
- (void)doneButtonTapped {
[[self presentingViewController] dismissViewControllerAnimated:YES
completion:nil];
// Convert seconds to miliseconds.
[self.delegate dateTimeChooser:self
didCloseSuccessfully:TRUE
withDate:self.selectedDate
forType:self.type];
}
- (void)datePickerValueChanged:(UIDatePicker*)datePicker {
self.selectedDate = datePicker.date;
}
// Adds subviews for a UI component with UIDatePicker and buttons.
//
// -------------------------------------
//
//
// UIDatePicker
//
//
// --------------------------------------
// | Cancel | flexibleSpace | Done |
// --------------------------------------
//
- (void)viewWillAppear:(BOOL)animated {
UIDatePicker* datePicker = [self createUIDatePicker];
// Create a ToolBar for buttons.
UIToolbar* toolbar = [[UIToolbar alloc]
initWithFrame:CGRectMake(0, 0, datePicker.frame.size.width,
kToolBarHeight)];
UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:@selector(cancelButtonTapped)];
UIBarButtonItem* flexibleSpace = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
UIBarButtonItem* doneButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:@selector(doneButtonTapped)];
// Add the UIBarButtonItem to the UIToolbar
[toolbar setItems:@[ cancelButton, flexibleSpace, doneButton ]];
// Vertical stack view that holds UIDatePicker and buttons.
UIStackView* verticalStack =
[[UIStackView alloc] initWithArrangedSubviews:@[ datePicker, toolbar ]];
verticalStack.axis = UILayoutConstraintAxisVertical;
verticalStack.spacing = 0;
verticalStack.distribution = UIStackViewDistributionFill;
verticalStack.layoutMarginsRelativeArrangement = YES;
verticalStack.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 0);
verticalStack.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:verticalStack];
[self.view setBounds:CGRectMake(CGRectGetMinX(datePicker.bounds),
CGRectGetMinY(datePicker.bounds),
CGRectGetWidth(datePicker.bounds),
CGRectGetHeight(datePicker.bounds) +
CGRectGetHeight(toolbar.bounds))];
}
@end