Commit 178757f0 authored by Justin Cohen's avatar Justin Cohen Committed by Commit Bot

[ios] Show collapsible header for content suggestions.

Adds new articles header view with a toggle button and
update logic to honor prefs::kArticlesListVisible.

Bug: 805638
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: I882cb19c9dd1bf6c1c6d232dab0413e01835a402
Reviewed-on: https://chromium-review.googlesource.com/964993Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#544378}
parent c2241812
...@@ -531,6 +531,9 @@ locale. The strings in this file are specific to iOS. ...@@ -531,6 +531,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_CONTENT_SUGGESTIONS_BOOKMARKS" desc="The Bookmarks title on the new tab page [Length: 10em]"> <message name="IDS_IOS_CONTENT_SUGGESTIONS_BOOKMARKS" desc="The Bookmarks title on the new tab page [Length: 10em]">
Bookmarks Bookmarks
</message> </message>
<message name="IDS_IOS_CONTENT_SUGGESTIONS_HIDE" desc="The label in the header to hide/collapse Content Suggestions [Length: 10em]">
Hide
</message>
<message name="IDS_IOS_CONTENT_SUGGESTIONS_HISTORY" desc="The History title on the new tab page [Length: 10em]"> <message name="IDS_IOS_CONTENT_SUGGESTIONS_HISTORY" desc="The History title on the new tab page [Length: 10em]">
History History
</message> </message>
...@@ -549,6 +552,9 @@ locale. The strings in this file are specific to iOS. ...@@ -549,6 +552,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_CONTENT_SUGGESTIONS_SETTING_TITLE" desc="The title of the settings to toggle the articles suggestions on the NTP on/off"> <message name="IDS_IOS_CONTENT_SUGGESTIONS_SETTING_TITLE" desc="The title of the settings to toggle the articles suggestions on the NTP on/off">
Article Suggestions Article Suggestions
</message> </message>
<message name="IDS_IOS_CONTENT_SUGGESTIONS_SHOW" desc="The label in the header to show/uncollapse Content Suggestions [Length: 10em]">
Show
</message>
<message name="IDS_IOS_CONTENT_SETTINGS_TITLE" desc="Title for content settings dialog [Length: 29em] [iOS only]"> <message name="IDS_IOS_CONTENT_SETTINGS_TITLE" desc="Title for content settings dialog [Length: 29em] [iOS only]">
Content Settings Content Settings
</message> </message>
......
...@@ -64,6 +64,7 @@ source_set("content_suggestions") { ...@@ -64,6 +64,7 @@ source_set("content_suggestions") {
"//ios/chrome/browser/ui/ntp:ntp_internal", "//ios/chrome/browser/ui/ntp:ntp_internal",
"//ios/chrome/browser/ui/overscroll_actions", "//ios/chrome/browser/ui/overscroll_actions",
"//ios/chrome/browser/ui/reading_list", "//ios/chrome/browser/ui/reading_list",
"//ios/chrome/browser/ui/settings/utils:utils",
"//ios/chrome/browser/ui/toolbar", "//ios/chrome/browser/ui/toolbar",
"//ios/chrome/browser/ui/toolbar:toolbar_ui", "//ios/chrome/browser/ui/toolbar:toolbar_ui",
"//ios/chrome/browser/ui/toolbar/adaptive:adaptive_ui", "//ios/chrome/browser/ui/toolbar/adaptive:adaptive_ui",
......
...@@ -33,6 +33,8 @@ source_set("cells") { ...@@ -33,6 +33,8 @@ source_set("cells") {
source_set("cells_ui") { source_set("cells_ui") {
sources = [ sources = [
"content_suggestions_articles_header_item.h",
"content_suggestions_articles_header_item.mm",
"content_suggestions_cell.h", "content_suggestions_cell.h",
"content_suggestions_cell.mm", "content_suggestions_cell.mm",
"content_suggestions_footer_item.h", "content_suggestions_footer_item.h",
......
// Copyright 2018 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_CONTENT_SUGGESTIONS_CELLS_CONTENT_SUGGESTIONS_ARTICLES_HEADER_ITEM_H_
#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_CONTENT_SUGGESTIONS_ARTICLES_HEADER_ITEM_H_
#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h"
@class ContentSuggestionsArticlesHeaderCell;
// Delegate for the cell.
@protocol ContentSuggestionsArticlesHeaderCellDelegate
// Notifies the delegate that the button of the |cell| has been tapped.
- (void)cellButtonTapped:(nonnull ContentSuggestionsArticlesHeaderCell*)cell;
@end
// Item for a ArticlesHeader of a Content Suggestions section. Displays a
// header title and a button to toggle the collapsed/expanded state.
@interface ContentSuggestionsArticlesHeaderItem
: CollectionViewItem<ContentSuggestionsArticlesHeaderCellDelegate>
@property(nonatomic, assign) BOOL expanded;
// Initializes an ArticlesHeader with a button aligned to the trailing edge,
// with a |title| and a |callback| run when the cell button is tapped.
- (nullable instancetype)initWithType:(NSInteger)type
title:(nonnull NSString*)title
callback:(void (^_Nullable)())callback
NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithType:(NSInteger)type NS_UNAVAILABLE;
@end
// Corresponding cell for a Content Suggestions' section ArticlesHeader.
@interface ContentSuggestionsArticlesHeaderCell : MDCCollectionViewCell
// Label used to indicate expanded state and trigger callback.
@property(nonatomic, readonly, strong, nonnull) UIButton* button;
// Label for this header items.
@property(nonatomic, strong, nonnull) UILabel* label;
@property(nonatomic, weak, nullable)
id<ContentSuggestionsArticlesHeaderCellDelegate>
delegate;
@end
#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_CONTENT_SUGGESTIONS_ARTICLES_HEADER_ITEM_H_
// Copyright 2017 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.
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_articles_header_item.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#import "ios/chrome/browser/ui/util/constraints_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 {
// Leading and trailing margin for label and button.
const CGFloat kTextMargin = 13;
// Color for label text.
const int kLabelColorRGB = 0x6D6D72;
}
#pragma mark - ContentSuggestionsArticlesHeaderItem
@interface ContentSuggestionsArticlesHeaderItem ()
@property(nonatomic, copy) NSString* title;
@property(nonatomic, copy) void (^callback)();
@end
@implementation ContentSuggestionsArticlesHeaderItem
@synthesize expanded = _expanded;
@synthesize title = _title;
@synthesize callback = _callback;
- (instancetype)initWithType:(NSInteger)type
title:(NSString*)title
callback:(void (^)())callback {
self = [super initWithType:type];
if (self) {
self.cellClass = [ContentSuggestionsArticlesHeaderCell class];
_title = [title copy];
_callback = [callback copy];
}
return self;
}
- (void)configureCell:(ContentSuggestionsArticlesHeaderCell*)cell {
[super configureCell:cell];
[cell.button
setTitle:self.expanded
? l10n_util::GetNSString(IDS_IOS_CONTENT_SUGGESTIONS_HIDE)
: l10n_util::GetNSString(IDS_IOS_CONTENT_SUGGESTIONS_SHOW)
forState:UIControlStateNormal];
cell.label.text = [self.title uppercaseString];
cell.delegate = self;
}
#pragma mark ContentSuggestionsArticlesHeaderCellDelegate
- (void)cellButtonTapped:(ContentSuggestionsArticlesHeaderCell*)cell {
if (self.callback) {
self.callback();
}
}
@end
#pragma mark - ContentSuggestionsArticlesHeaderCell
@implementation ContentSuggestionsArticlesHeaderCell
@synthesize button = _button;
@synthesize delegate = _delegate;
@synthesize label = _label;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_label = [[UILabel alloc] init];
_label.translatesAutoresizingMaskIntoConstraints = NO;
_label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
_label.textColor = UIColorFromRGB(kLabelColorRGB, 1.0);
_label.adjustsFontSizeToFitWidth = YES;
_button = [UIButton buttonWithType:UIButtonTypeSystem];
_button.translatesAutoresizingMaskIntoConstraints = NO;
_button.titleLabel.font =
[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
[_button addTarget:self
action:@selector(buttonTapped)
forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:_button];
[self.contentView addSubview:_label];
[NSLayoutConstraint activateConstraints:@[
[_label.leadingAnchor
constraintEqualToAnchor:self.contentView.leadingAnchor
constant:kTextMargin],
[_label.topAnchor constraintEqualToAnchor:self.contentView.topAnchor],
[_label.bottomAnchor
constraintEqualToAnchor:self.contentView.bottomAnchor],
[_button.trailingAnchor
constraintEqualToAnchor:self.contentView.trailingAnchor
constant:-kTextMargin],
[_button.topAnchor constraintEqualToAnchor:self.contentView.topAnchor],
[_button.bottomAnchor
constraintEqualToAnchor:self.contentView.bottomAnchor],
[_label.trailingAnchor
constraintLessThanOrEqualToAnchor:_button.leadingAnchor]
]];
}
return self;
}
- (void)prepareForReuse {
[super prepareForReuse];
self.delegate = nil;
}
#pragma mark Private
// Callback for the button action.
- (void)buttonTapped {
[self.delegate cellButtonTapped:self];
}
@end
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h"
#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
#import "ios/chrome/browser/ui/commands/snackbar_commands.h" #import "ios/chrome/browser/ui/commands/snackbar_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_articles_header_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_footer_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_footer_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_header_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_header_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_text_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_text_item.h"
...@@ -504,6 +505,7 @@ addSuggestionsToModel:(NSArray<CSCollectionViewItem*>*)suggestions ...@@ -504,6 +505,7 @@ addSuggestionsToModel:(NSArray<CSCollectionViewItem*>*)suggestions
} else { } else {
[self addHeaderIfNeeded:sectionInfo]; [self addHeaderIfNeeded:sectionInfo];
} }
if (sectionInfo.expanded)
[self addFooterIfNeeded:sectionInfo]; [self addFooterIfNeeded:sectionInfo];
} }
...@@ -637,12 +639,13 @@ addSuggestionsToModel:(NSArray<CSCollectionViewItem*>*)suggestions ...@@ -637,12 +639,13 @@ addSuggestionsToModel:(NSArray<CSCollectionViewItem*>*)suggestions
BOOL addHeader = YES; BOOL addHeader = YES;
if (IsFromContentSuggestionsService(sectionIdentifier)) { if (IsFromContentSuggestionsService(sectionIdentifier)) {
addHeader = NO; addHeader = IsUIRefreshPhase1Enabled();
if ([self.sectionIdentifiersFromContentSuggestions if ([self.sectionIdentifiersFromContentSuggestions
containsObject:@(sectionIdentifier)]) { containsObject:@(sectionIdentifier)]) {
return; return;
} }
if ([self.sectionIdentifiersFromContentSuggestions count] == 1) { if ([self.sectionIdentifiersFromContentSuggestions count] == 1) {
NSNumber* existingSectionIdentifier = NSNumber* existingSectionIdentifier =
[self.sectionIdentifiersFromContentSuggestions anyObject]; [self.sectionIdentifiersFromContentSuggestions anyObject];
...@@ -669,6 +672,19 @@ addSuggestionsToModel:(NSArray<CSCollectionViewItem*>*)suggestions ...@@ -669,6 +672,19 @@ addSuggestionsToModel:(NSArray<CSCollectionViewItem*>*)suggestions
// Returns the header for this |sectionInfo|. // Returns the header for this |sectionInfo|.
- (CollectionViewItem*)headerForSectionInfo: - (CollectionViewItem*)headerForSectionInfo:
(ContentSuggestionsSectionInformation*)sectionInfo { (ContentSuggestionsSectionInformation*)sectionInfo {
if (IsUIRefreshPhase1Enabled()) {
DCHECK(SectionIdentifierForInfo(sectionInfo) == SectionIdentifierArticles);
__weak ContentSuggestionsCollectionUpdater* weakSelf = self;
ContentSuggestionsArticlesHeaderItem* header =
[[ContentSuggestionsArticlesHeaderItem alloc]
initWithType:ItemTypeHeader
title:sectionInfo.title
callback:^() {
[weakSelf.dataSource toggleArticlesVisibility];
}];
header.expanded = sectionInfo.expanded;
return header;
}
CollectionViewTextItem* header = CollectionViewTextItem* header =
[[CollectionViewTextItem alloc] initWithType:ItemTypeHeader]; [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader];
header.text = sectionInfo.title; header.text = sectionInfo.title;
...@@ -800,7 +816,7 @@ addSuggestionsToModel:(NSArray<CSCollectionViewItem*>*)suggestions ...@@ -800,7 +816,7 @@ addSuggestionsToModel:(NSArray<CSCollectionViewItem*>*)suggestions
// Returns nil if there is no empty item for this section info. // Returns nil if there is no empty item for this section info.
- (CSCollectionViewItem*)emptyItemForSectionInfo: - (CSCollectionViewItem*)emptyItemForSectionInfo:
(ContentSuggestionsSectionInformation*)sectionInfo { (ContentSuggestionsSectionInformation*)sectionInfo {
if (!sectionInfo.emptyText) if (!sectionInfo.emptyText || !sectionInfo.expanded)
return nil; return nil;
ContentSuggestionsTextItem* item = ContentSuggestionsTextItem* item =
[[ContentSuggestionsTextItem alloc] initWithType:ItemTypeEmpty]; [[ContentSuggestionsTextItem alloc] initWithType:ItemTypeEmpty];
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/mac/foundation_util.h" #include "base/mac/foundation_util.h"
#include "components/ntp_snippets/content_suggestions_service.h" #include "components/ntp_snippets/content_suggestions_service.h"
#include "components/ntp_snippets/pref_names.h"
#include "components/ntp_snippets/remote/remote_suggestions_scheduler.h" #include "components/ntp_snippets/remote/remote_suggestions_scheduler.h"
#include "components/ntp_tiles/most_visited_sites.h" #include "components/ntp_tiles/most_visited_sites.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
...@@ -32,6 +33,7 @@ ...@@ -32,6 +33,7 @@
#import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
#import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h" #import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h"
#import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h" #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
#import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h"
#import "ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h" #import "ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h"
#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.h" #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.h"
#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_visibility_configuration.h" #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_visibility_configuration.h"
...@@ -172,6 +174,14 @@ ...@@ -172,6 +174,14 @@
readingListModel:readingListModel]; readingListModel:readingListModel];
self.contentSuggestionsMediator.commandHandler = self.NTPMediator; self.contentSuggestionsMediator.commandHandler = self.NTPMediator;
self.contentSuggestionsMediator.headerProvider = self.headerController; self.contentSuggestionsMediator.headerProvider = self.headerController;
self.contentSuggestionsMediator.contentArticlesExpanded =
[[PrefBackedBoolean alloc]
initWithPrefService:prefs
prefName:ntp_snippets::prefs::kArticlesListVisible];
self.contentSuggestionsMediator.contentArticlesEnabled =
[[PrefBackedBoolean alloc]
initWithPrefService:prefs
prefName:prefs::kArticlesForYouEnabled];
self.headerController.promoCanShow = self.headerController.promoCanShow =
[self.contentSuggestionsMediator notificationPromo]->CanShow(); [self.contentSuggestionsMediator notificationPromo]->CanShow();
......
...@@ -66,6 +66,10 @@ typedef void (^MoreSuggestionsFetched)( ...@@ -66,6 +66,10 @@ typedef void (^MoreSuggestionsFetched)(
// Returns the header view containing the logo and omnibox to be displayed. // Returns the header view containing the logo and omnibox to be displayed.
- (nullable UIView*)headerViewForWidth:(CGFloat)width; - (nullable UIView*)headerViewForWidth:(CGFloat)width;
// Toggles the preference that controls content suggestions articles visilibity
// and triggers an update for the necessary data sources.
- (void)toggleArticlesVisibility;
@end @end
#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_DATA_SOURCE_H_ #endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_DATA_SOURCE_H_
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_source.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_source.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.h"
#import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h"
namespace favicon { namespace favicon {
class LargeIconService; class LargeIconService;
...@@ -62,6 +63,13 @@ initWithContentService: ...@@ -62,6 +63,13 @@ initWithContentService:
@property(nonatomic, weak, nullable) id<ContentSuggestionsHeaderProvider> @property(nonatomic, weak, nullable) id<ContentSuggestionsHeaderProvider>
headerProvider; headerProvider;
// Whether the contents section should be expanded or collapsed. Collapsed
// means to show the header, but not any content or footer.
@property(nullable, nonatomic, strong)
PrefBackedBoolean* contentArticlesExpanded;
// Whether the contents secction should be hidden completely.
@property(nullable, nonatomic, strong)
PrefBackedBoolean* contentArticlesEnabled;
// Whether to force the reload the Reading List section next time it is updated. // Whether to force the reload the Reading List section next time it is updated.
// Reset to NO after actual reload. // Reset to NO after actual reload.
@property(nonatomic, assign) BOOL readingListNeedsReload; @property(nonatomic, assign) BOOL readingListNeedsReload;
......
...@@ -108,6 +108,9 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -108,6 +108,9 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
ContentSuggestionsMostVisitedActionItem* readingListItem; ContentSuggestionsMostVisitedActionItem* readingListItem;
// Number of unread items in reading list model. // Number of unread items in reading list model.
@property(nonatomic, assign) NSInteger readingListUnreadCount; @property(nonatomic, assign) NSInteger readingListUnreadCount;
// Whether to force the reload the Articles List section next time it is
// updated. Reset to NO after actual reload.
@property(nonatomic, assign) BOOL articlesListNeedsReload;
@end @end
...@@ -129,8 +132,11 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -129,8 +132,11 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
@synthesize faviconMediator = _faviconMediator; @synthesize faviconMediator = _faviconMediator;
@synthesize learnMoreItem = _learnMoreItem; @synthesize learnMoreItem = _learnMoreItem;
@synthesize readingListNeedsReload = _readingListNeedsReload; @synthesize readingListNeedsReload = _readingListNeedsReload;
@synthesize articlesListNeedsReload = _articlesListNeedsReload;
@synthesize readingListItem = _readingListItem; @synthesize readingListItem = _readingListItem;
@synthesize readingListUnreadCount = _readingListUnreadCount; @synthesize readingListUnreadCount = _readingListUnreadCount;
@synthesize contentArticlesExpanded = _contentArticlesExpanded;
@synthesize contentArticlesEnabled = _contentArticlesEnabled;
#pragma mark - Public #pragma mark - Public
...@@ -229,8 +235,7 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService ...@@ -229,8 +235,7 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService
if (!self.sectionInformationByCategory[categoryWrapper]) { if (!self.sectionInformationByCategory[categoryWrapper]) {
[self addSectionInformationForCategory:category]; [self addSectionInformationForCategory:category];
} }
if (IsCategoryStatusAvailable( if ([self isCategoryAvailable:category]) {
self.contentService->GetCategoryStatus(category))) {
[sectionsInfo [sectionsInfo
addObject:self.sectionInformationByCategory[categoryWrapper]]; addObject:self.sectionInformationByCategory[categoryWrapper]];
} }
...@@ -365,6 +370,24 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService ...@@ -365,6 +370,24 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService
return [self.headerProvider headerForWidth:width]; return [self.headerProvider headerForWidth:width];
} }
- (void)toggleArticlesVisibility {
[self.contentArticlesExpanded setValue:![self.contentArticlesExpanded value]];
// Update the section information for new collapsed state.
ntp_snippets::Category category = ntp_snippets::Category::FromKnownCategory(
ntp_snippets::KnownCategories::ARTICLES);
ContentSuggestionsCategoryWrapper* wrapper =
[ContentSuggestionsCategoryWrapper wrapperWithCategory:category];
ContentSuggestionsSectionInformation* sectionInfo =
self.sectionInformationByCategory[wrapper];
sectionInfo.expanded = [self.contentArticlesExpanded value];
self.sectionInformationByCategory[wrapper] = sectionInfo;
// Reload the data model.
self.articlesListNeedsReload = YES;
[self.dataSink reloadAllData];
}
#pragma mark - ContentSuggestionsServiceObserver #pragma mark - ContentSuggestionsServiceObserver
- (void)contentSuggestionsService: - (void)contentSuggestionsService:
...@@ -381,8 +404,12 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService ...@@ -381,8 +404,12 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService
self.readingListNeedsReload = NO; self.readingListNeedsReload = NO;
} }
if (ntp_snippets::IsCategoryStatusAvailable( if (category.IsKnownCategory(ntp_snippets::KnownCategories::ARTICLES)) {
self.contentService->GetCategoryStatus(category))) { forceReload = self.articlesListNeedsReload;
self.articlesListNeedsReload = NO;
}
if ([self isCategoryAvailable:category]) {
[self.dataSink [self.dataSink
dataAvailableForSection:self.sectionInformationByCategory[wrapper] dataAvailableForSection:self.sectionInformationByCategory[wrapper]
forceReload:forceReload]; forceReload:forceReload];
...@@ -395,7 +422,7 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService ...@@ -395,7 +422,7 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService
statusChangedTo:(ntp_snippets::CategoryStatus)status { statusChangedTo:(ntp_snippets::CategoryStatus)status {
ContentSuggestionsCategoryWrapper* wrapper = ContentSuggestionsCategoryWrapper* wrapper =
[[ContentSuggestionsCategoryWrapper alloc] initWithCategory:category]; [[ContentSuggestionsCategoryWrapper alloc] initWithCategory:category];
if (!ntp_snippets::IsCategoryStatusInitOrAvailable(status)) { if (![self isCategoryInitOrAvailable:category]) {
// Remove the category from the UI if it is not available. // Remove the category from the UI if it is not available.
ContentSuggestionsSectionInformation* sectionInfo = ContentSuggestionsSectionInformation* sectionInfo =
self.sectionInformationByCategory[wrapper]; self.sectionInformationByCategory[wrapper];
...@@ -531,8 +558,7 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService ...@@ -531,8 +558,7 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService
(const std::vector<ntp_snippets::ContentSuggestion>&)suggestions (const std::vector<ntp_snippets::ContentSuggestion>&)suggestions
fromCategory:(ntp_snippets::Category&)category fromCategory:(ntp_snippets::Category&)category
toItemArray:(NSMutableArray<CSCollectionViewItem*>*)itemArray { toItemArray:(NSMutableArray<CSCollectionViewItem*>*)itemArray {
if (!ntp_snippets::IsCategoryStatusAvailable( if (![self isCategoryExpanded:category]) {
self.contentService->GetCategoryStatus(category))) {
return; return;
} }
...@@ -561,8 +587,9 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService ...@@ -561,8 +587,9 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService
base::Optional<ntp_snippets::CategoryInfo> categoryInfo = base::Optional<ntp_snippets::CategoryInfo> categoryInfo =
self.contentService->GetCategoryInfo(category); self.contentService->GetCategoryInfo(category);
BOOL expanded = [self isCategoryExpanded:category];
ContentSuggestionsSectionInformation* sectionInfo = ContentSuggestionsSectionInformation* sectionInfo =
SectionInformationFromCategoryInfo(categoryInfo, category); SectionInformationFromCategoryInfo(categoryInfo, category, expanded);
self.sectionInformationByCategory[[ContentSuggestionsCategoryWrapper self.sectionInformationByCategory[[ContentSuggestionsCategoryWrapper
wrapperWithCategory:category]] = sectionInfo; wrapperWithCategory:category]] = sectionInfo;
...@@ -599,6 +626,47 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService ...@@ -599,6 +626,47 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService
[self.dataSink reloadSection:self.mostVisitedSectionInfo]; [self.dataSink reloadSection:self.mostVisitedSectionInfo];
} }
// ntp_snippets doesn't differentiate between disabled vs collapsed, so if
// the status is |CATEGORY_EXPLICITLY_DISABLED|, check the value of
// |contentArticlesEnabled|.
- (BOOL)isCategoryInitOrAvailable:(ntp_snippets::Category)category {
ntp_snippets::CategoryStatus status =
self.contentService->GetCategoryStatus(category);
if (IsUIRefreshPhase1Enabled() &&
category.IsKnownCategory(ntp_snippets::KnownCategories::ARTICLES) &&
status == ntp_snippets::CategoryStatus::CATEGORY_EXPLICITLY_DISABLED)
return [self.contentArticlesEnabled value];
else
return IsCategoryStatusInitOrAvailable(
self.contentService->GetCategoryStatus(category));
}
// ntp_snippets doesn't differentiate between disabled vs collapsed, so if
// the status is |CATEGORY_EXPLICITLY_DISABLED|, check the value of
// |contentArticlesEnabled|.
- (BOOL)isCategoryAvailable:(ntp_snippets::Category)category {
ntp_snippets::CategoryStatus status =
self.contentService->GetCategoryStatus(category);
if (IsUIRefreshPhase1Enabled() &&
category.IsKnownCategory(ntp_snippets::KnownCategories::ARTICLES) &&
status == ntp_snippets::CategoryStatus::CATEGORY_EXPLICITLY_DISABLED) {
return [self.contentArticlesEnabled value];
} else {
return IsCategoryStatusAvailable(
self.contentService->GetCategoryStatus(category));
}
}
// Returns whether the Articles category pref indicates it should be expanded,
// otherwise returns YES.
- (BOOL)isCategoryExpanded:(ntp_snippets::Category)category {
if (IsUIRefreshPhase1Enabled() &&
category.IsKnownCategory(ntp_snippets::KnownCategories::ARTICLES))
return [self.contentArticlesExpanded value];
else
return YES;
}
#pragma mark - Properties #pragma mark - Properties
- (NSArray<ContentSuggestionsMostVisitedActionItem*>*)actionButtonItems { - (NSArray<ContentSuggestionsMostVisitedActionItem*>*)actionButtonItems {
......
...@@ -51,6 +51,9 @@ typedef NS_ENUM(NSInteger, ContentSuggestionsSectionID) { ...@@ -51,6 +51,9 @@ typedef NS_ENUM(NSInteger, ContentSuggestionsSectionID) {
// empty because the user dismissed suggestions, the |emptyText| must be shown // empty because the user dismissed suggestions, the |emptyText| must be shown
// in both cases. // in both cases.
@property(nonatomic, assign) BOOL showIfEmpty; @property(nonatomic, assign) BOOL showIfEmpty;
// If the section should be expanded (fully visible) or collapsed (only show the
// header).
@property(nonatomic, assign) BOOL expanded;
@end @end
......
...@@ -18,12 +18,14 @@ ...@@ -18,12 +18,14 @@
@synthesize footerTitle = _footerTitle; @synthesize footerTitle = _footerTitle;
@synthesize emptyText = _emptyText; @synthesize emptyText = _emptyText;
@synthesize showIfEmpty = _showIfEmpty; @synthesize showIfEmpty = _showIfEmpty;
@synthesize expanded = _expanded;
- (instancetype)initWithSectionID:(ContentSuggestionsSectionID)sectionID { - (instancetype)initWithSectionID:(ContentSuggestionsSectionID)sectionID {
self = [super init]; self = [super init];
if (self) { if (self) {
DCHECK(sectionID < ContentSuggestionsSectionUnknown); DCHECK(sectionID < ContentSuggestionsSectionUnknown);
_sectionID = sectionID; _sectionID = sectionID;
_expanded = YES;
} }
return self; return self;
} }
......
...@@ -45,10 +45,11 @@ ContentSuggestionsItem* ConvertSuggestion( ...@@ -45,10 +45,11 @@ ContentSuggestionsItem* ConvertSuggestion(
ntp_snippets::Category category); ntp_snippets::Category category);
// Returns a SectionInformation for a |category|, filled with the // Returns a SectionInformation for a |category|, filled with the
// |categoryInfo|. // |categoryInfo| and |expanded|.
ContentSuggestionsSectionInformation* SectionInformationFromCategoryInfo( ContentSuggestionsSectionInformation* SectionInformationFromCategoryInfo(
const base::Optional<ntp_snippets::CategoryInfo>& categoryInfo, const base::Optional<ntp_snippets::CategoryInfo>& categoryInfo,
const ntp_snippets::Category& category); const ntp_snippets::Category& category,
const BOOL expanded);
// Returns a ntp_snippets::ID based on a Objective-C Category and the ID in the // Returns a ntp_snippets::ID based on a Objective-C Category and the ID in the
// category. // category.
......
...@@ -92,7 +92,8 @@ ContentSuggestionsItem* ConvertSuggestion( ...@@ -92,7 +92,8 @@ ContentSuggestionsItem* ConvertSuggestion(
ContentSuggestionsSectionInformation* SectionInformationFromCategoryInfo( ContentSuggestionsSectionInformation* SectionInformationFromCategoryInfo(
const base::Optional<ntp_snippets::CategoryInfo>& categoryInfo, const base::Optional<ntp_snippets::CategoryInfo>& categoryInfo,
const ntp_snippets::Category& category) { const ntp_snippets::Category& category,
const BOOL expanded) {
ContentSuggestionsSectionInformation* sectionInfo = ContentSuggestionsSectionInformation* sectionInfo =
[[ContentSuggestionsSectionInformation alloc] [[ContentSuggestionsSectionInformation alloc]
initWithSectionID:SectionIDForCategory(category)]; initWithSectionID:SectionIDForCategory(category)];
...@@ -107,6 +108,7 @@ ContentSuggestionsSectionInformation* SectionInformationFromCategoryInfo( ...@@ -107,6 +108,7 @@ ContentSuggestionsSectionInformation* SectionInformationFromCategoryInfo(
l10n_util::GetNSString(IDS_IOS_CONTENT_SUGGESTIONS_FOOTER_TITLE); l10n_util::GetNSString(IDS_IOS_CONTENT_SUGGESTIONS_FOOTER_TITLE);
} }
sectionInfo.title = base::SysUTF16ToNSString(categoryInfo->title()); sectionInfo.title = base::SysUTF16ToNSString(categoryInfo->title());
sectionInfo.expanded = expanded;
} }
return sectionInfo; return sectionInfo;
} }
......
...@@ -140,6 +140,9 @@ using CSCollectionViewItem = CollectionViewItem<SuggestedContent>; ...@@ -140,6 +140,9 @@ using CSCollectionViewItem = CollectionViewItem<SuggestedContent>;
return nil; return nil;
} }
- (void)toggleArticlesVisibility {
}
#pragma mark - Property #pragma mark - Property
- (ContentSuggestionsSectionInformation*)logoHeaderSection { - (ContentSuggestionsSectionInformation*)logoHeaderSection {
......
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