Commit ef91bbc8 authored by Jeffrey Cohen's avatar Jeffrey Cohen Committed by Commit Bot

[SendTabToSelf] add target devices to Table View Controller

This CL fleshes out the TVC to both display properly and to
enumerate the possible target devices that a user can send a tab.

screenshot of current state:
https://drive.google.com/file/d/1iF1unVcXoKFk-l3bFh1GrQTe6ve5KZtB/view

Bug: 970284
Change-Id: I64b5afbbf56b9deaca63ce416f835051cc57b56a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1664994Reviewed-by: default avatarSergio Collazos <sczs@chromium.org>
Commit-Queue: Jeffrey Cohen <jeffreycohen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#672730}
parent 8013333a
......@@ -11,12 +11,18 @@ source_set("send_tab_to_self") {
deps = [
":send_tab_to_self_ui",
"//base",
"//components/send_tab_to_self",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/main",
"//ios/chrome/browser/sync",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators",
"//ios/chrome/browser/ui/infobars/presentation",
]
}
source_set("send_tab_to_self_ui") {
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
"send_tab_to_self_modal_positioner.h",
"send_tab_to_self_modal_presentation_controller.h",
"send_tab_to_self_modal_presentation_controller.mm",
"send_tab_to_self_table_view_controller.h",
......@@ -24,7 +30,11 @@ source_set("send_tab_to_self_ui") {
]
deps = [
"//base",
"//components/send_tab_to_self",
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/browser/ui/table_view",
"//ios/chrome/browser/ui/table_view:styler",
"//ios/chrome/browser/ui/table_view/cells",
"//ui/base",
]
}
......@@ -5,6 +5,10 @@
#import "ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_coordinator.h"
#include "base/logging.h"
#include "components/send_tab_to_self/send_tab_to_self_sync_service.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/sync/send_tab_to_self_sync_service_factory.h"
#import "ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_modal_positioner.h"
#import "ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_modal_presentation_controller.h"
#import "ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_table_view_controller.h"
......@@ -12,12 +16,17 @@
#error "This file requires ARC support."
#endif
@interface SendTabToSelfCoordinator () <UIViewControllerTransitioningDelegate>
@interface SendTabToSelfCoordinator () <UIViewControllerTransitioningDelegate,
SendTabToSelfModalPositioner>
// The presentationController that shows the Send Tab To Self UI.
@property(nonatomic, strong) SendTabToSelfModalPresentationController*
sendTabToSelfModalPresentationController;
// The presentationController that shows the Send Tab To Self UI.
@property(nonatomic, strong)
SendTabToSelfTableViewController* sendTabToSelfViewController;
@end
@implementation SendTabToSelfCoordinator
......@@ -25,10 +34,16 @@
#pragma mark - ChromeCoordinator Methods
- (void)start {
SendTabToSelfTableViewController* tableViewController =
[[SendTabToSelfTableViewController alloc] init];
send_tab_to_self::SendTabToSelfSyncService* syncService =
SendTabToSelfSyncServiceFactory::GetForBrowserState(self.browserState);
// This modal should not be launched in incognito mode where syncService is
// undefined.
DCHECK(syncService);
self.sendTabToSelfViewController = [[SendTabToSelfTableViewController alloc]
initWithModel:syncService->GetSendTabToSelfModel()];
UINavigationController* navigationController = [[UINavigationController alloc]
initWithRootViewController:tableViewController];
initWithRootViewController:self.sendTabToSelfViewController];
navigationController.transitioningDelegate = self;
navigationController.modalPresentationStyle = UIModalPresentationCustom;
......@@ -53,8 +68,24 @@
[[SendTabToSelfModalPresentationController alloc]
initWithPresentedViewController:presented
presentingViewController:presenting];
// TODO(crbug.com/970284) flesh out presentationController.
presentationController.modalPositioner = self;
return presentationController;
}
#pragma mark - SendTabToSelfModalPositioner
- (CGFloat)modalHeight {
UITableView* tableView = self.sendTabToSelfViewController.tableView;
[tableView setNeedsLayout];
[tableView layoutIfNeeded];
// Since the TableView is contained in a NavigationController get the
// navigation bar height.
CGFloat navigationBarHeight =
self.sendTabToSelfViewController.navigationController.navigationBar.frame
.size.height;
return tableView.contentSize.height + navigationBarHeight;
}
@end
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_UI_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_MODAL_POSITIONER_H_
#define IOS_CHROME_BROWSER_UI_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_MODAL_POSITIONER_H_
#import <UIKit/UIKit.h>
// SendTabToSelfModalPositioner contains methods used to position the send tab
// to self modal dialog.
@protocol SendTabToSelfModalPositioner
// The target height for the modal view to be presented.
- (CGFloat)modalHeight;
@end
#endif // IOS_CHROME_BROWSER_UI_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_MODAL_POSITIONER_H_
......@@ -7,9 +7,14 @@
#import <UIKit/UIKit.h>
@protocol SendTabToSelfModalPositioner;
// PresentationController for the modal dialog.
@interface SendTabToSelfModalPresentationController : UIPresentationController
// Delegate used to position the modal dialog.
@property(nonatomic, weak) id<SendTabToSelfModalPositioner> modalPositioner;
@end
#endif // IOS_CHROME_BROWSER_UI_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_MODAL_PRESENTATION_CONTROLLER_H_
......@@ -4,10 +4,60 @@
#import "ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_modal_presentation_controller.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_modal_positioner.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// The presented view outer horizontal margins.
const CGFloat kPresentedViewMargin = 10.0;
// The presented view maximum width.
const CGFloat kPresentedViewMaxWidth = 394.0;
// The rounded corner radius for the container view.
const CGFloat kContainerCornerRadius = 13.0;
// The background color for the container view.
const int kContainerBackgroundColor = 0x2F2F2F;
// The alpha component for the container view background color.
const CGFloat kContainerBackgroundColorAlpha = 0.5;
} // namespace
@implementation SendTabToSelfModalPresentationController
- (void)containerViewWillLayoutSubviews {
self.presentedView.frame = [self frameForPresentedView];
// Style the presented and container views.
self.presentedView.layer.cornerRadius = kContainerCornerRadius;
self.presentedView.layer.masksToBounds = YES;
self.presentedView.clipsToBounds = YES;
self.containerView.backgroundColor =
[UIColorFromRGB(kContainerBackgroundColor)
colorWithAlphaComponent:kContainerBackgroundColorAlpha];
}
- (CGRect)frameForPresentedView {
DCHECK(self.modalPositioner);
CGFloat containerWidth = CGRectGetWidth(self.containerView.bounds);
CGFloat containerHeight = CGRectGetHeight(self.containerView.bounds);
// Calculate the frame width.
CGFloat maxAvailableWidth = containerWidth - 2 * kPresentedViewMargin;
CGFloat frameWidth = fmin(maxAvailableWidth, kPresentedViewMaxWidth);
CGFloat modalTargetHeight = [self.modalPositioner modalHeight];
CGFloat maxAvailableHeight = containerHeight - 2 * kPresentedViewMargin;
CGFloat frameHeight = fmin(maxAvailableHeight, modalTargetHeight);
// Based on the container width calculate the values in order to center the
// frame in the X and Y axis.
CGFloat modalXPosition = (containerWidth / 2) - (frameWidth / 2);
CGFloat modalYPosition = (containerHeight / 2) - (frameHeight / 2);
return CGRectMake(modalXPosition, modalYPosition, frameWidth, frameHeight);
}
@end
......@@ -7,15 +7,26 @@
#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
namespace send_tab_to_self {
class SendTabToSelfModel;
}
// SendTabToSelfTableViewController represents the content for the
// Send Tab To Self Modal dialog.
@interface SendTabToSelfTableViewController : ChromeTableViewController
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithModel:
(send_tab_to_self::SendTabToSelfModel*)sendTabToSelfModel
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithTableViewStyle:(UITableViewStyle)style
appBarStyle:
(ChromeTableViewControllerStyle)appBarStyle
NS_UNAVAILABLE;
// The text used for the cancel button.
@property(nonatomic, copy) NSString* cancelButtonText;
@end
#endif // IOS_CHROME_BROWSER_UI_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_TABLE_VIEW_CONTROLLER_H_
......@@ -5,27 +5,148 @@
#import "ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_table_view_controller.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "components/send_tab_to_self/send_tab_to_self_model.h"
#include "components/send_tab_to_self/target_device_info.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_icon_item.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h"
#include "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h"
#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Text color for the Cancel button.
const CGFloat kSendButtonBackgroundColorBlue = 0x1A73E8;
// Accessibility identifier of the Modal Cancel Button.
NSString* const kSendTabToSelfModalCancelButton =
@"kSendTabToSelfModalCancelButton";
// Accessibility identifier of the Modal Cancel Button.
NSString* const kSendTabToSelfModalSendButton =
@"kSendTabToSelfModalSendButton";
} // namespace
typedef NS_ENUM(NSInteger, SectionIdentifier) {
SectionIdentifierDevicesToSend = kSectionIdentifierEnumZero,
SectionIdentifierActionButton,
};
typedef NS_ENUM(NSInteger, ItemType) {
ItemTypeSend = kItemTypeEnumZero,
ItemTypeDevice,
};
@interface SendTabToSelfTableViewController () {
std::map<std::string, send_tab_to_self::TargetDeviceInfo> _target_device_map;
}
// Item that holds the cancel Button for this Infobar. e.g. "Never Save for this
// site".
@property(nonatomic, strong) TableViewTextButtonItem* sendToDevice;
@end
@implementation SendTabToSelfTableViewController
- (instancetype)init {
return [super initWithTableViewStyle:UITableViewStylePlain
- (instancetype)initWithModel:
(send_tab_to_self::SendTabToSelfModel*)sendTabToSelfModel {
self = [super initWithTableViewStyle:UITableViewStylePlain
appBarStyle:ChromeTableViewControllerStyleNoAppBar];
if (self) {
_target_device_map =
sendTabToSelfModel->GetTargetDeviceNameToCacheInfoMap();
}
return self;
}
#pragma mark - ViewController Lifecycle
- (void)viewDidLoad {
NOTIMPLEMENTED();
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.styler.cellBackgroundColor = [UIColor whiteColor];
self.tableView.sectionHeaderHeight = 0;
[self.tableView
setSeparatorInset:UIEdgeInsetsMake(0, kTableViewHorizontalSpacing, 0, 0)];
// Configure the NavigationBar.
UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:nil];
cancelButton.accessibilityIdentifier = kSendTabToSelfModalCancelButton;
self.navigationItem.leftBarButtonItem = cancelButton;
self.navigationItem.title =
l10n_util::GetNSString(IDS_IOS_SEND_TAB_TO_SELF_TARGET_DEVICE_TITLE);
self.navigationController.navigationBar.prefersLargeTitles = NO;
[self loadModel];
}
#pragma mark - TableViewModel
- (void)loadModel {
[super loadModel];
TableViewModel* model = self.tableViewModel;
[model addSectionWithIdentifier:SectionIdentifierDevicesToSend];
for (auto const& iter : _target_device_map) {
int daysSinceLastUpdate =
(base::Time::Now() - iter.second.last_updated_timestamp).InDays();
TableViewDetailIconItem* deviceItem =
[[TableViewDetailIconItem alloc] initWithType:ItemTypeDevice];
deviceItem.text = base::SysUTF8ToNSString(iter.first);
deviceItem.detailText =
[self sendTabToSelfdaysSinceLastUpdate:daysSinceLastUpdate];
[model addItem:deviceItem
toSectionWithIdentifier:SectionIdentifierDevicesToSend];
}
[model addSectionWithIdentifier:SectionIdentifierActionButton];
self.sendToDevice =
[[TableViewTextButtonItem alloc] initWithType:ItemTypeSend];
self.sendToDevice.buttonText =
l10n_util::GetNSString(IDS_IOS_SEND_TAB_TO_SELF_TARGET_DEVICE_ACTION);
self.sendToDevice.buttonTextColor = [UIColor whiteColor];
;
self.sendToDevice.buttonBackgroundColor =
UIColorFromRGB(kSendButtonBackgroundColorBlue);
self.sendToDevice.boldButtonText = NO;
self.sendToDevice.accessibilityIdentifier = kSendTabToSelfModalSendButton;
[model addItem:self.sendToDevice
toSectionWithIdentifier:SectionIdentifierActionButton];
}
#pragma mark - Helpers
- (NSString*)sendTabToSelfdaysSinceLastUpdate:(int)days {
NSString* active_time;
if (days == 0) {
active_time = l10n_util::GetNSString(
IDS_IOS_SEND_TAB_TO_SELF_TARGET_DEVICE_ITEM_SUBTITLE_TODAY);
} else if (days == 1) {
active_time = l10n_util::GetNSString(
IDS_IOS_SEND_TAB_TO_SELF_TARGET_DEVICE_ITEM_SUBTITLE_DAY);
} else {
active_time = l10n_util::GetNSStringF(
IDS_IOS_SEND_TAB_TO_SELF_TARGET_DEVICE_ITEM_SUBTITLE_DAYS,
base::NumberToString16(days));
}
return active_time;
}
@end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment