| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ios/chrome/browser/ui/history/history_collection_view_controller.h" | 5 #include "ios/chrome/browser/ui/history/history_collection_view_controller.h" |
| 6 | 6 |
| 7 #import <MobileCoreServices/MobileCoreServices.h> | 7 #import <MobileCoreServices/MobileCoreServices.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #import "base/ios/weak_nsobject.h" | 11 #import "base/ios/weak_nsobject.h" |
| 12 #include "base/mac/foundation_util.h" | 12 #include "base/mac/foundation_util.h" |
| 13 #import "base/mac/objc_property_releaser.h" | 13 #import "base/mac/objc_property_releaser.h" |
| 14 #include "base/mac/scoped_nsobject.h" | 14 #include "base/mac/scoped_nsobject.h" |
| 15 #include "base/strings/sys_string_conversions.h" | 15 #include "base/strings/sys_string_conversions.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 17 #include "components/browsing_data/core/history_notice_utils.h" | 17 #include "components/browsing_data/core/history_notice_utils.h" |
| 18 #include "components/strings/grit/components_strings.h" | 18 #include "components/strings/grit/components_strings.h" |
| 19 #include "components/url_formatter/url_formatter.h" | 19 #include "components/url_formatter/url_formatter.h" |
| 20 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" | 20 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 21 #include "ios/chrome/browser/chrome_url_constants.h" | 21 #include "ios/chrome/browser/chrome_url_constants.h" |
| 22 #import "ios/chrome/browser/signin/authentication_service.h" | 22 #import "ios/chrome/browser/signin/authentication_service.h" |
| 23 #include "ios/chrome/browser/signin/authentication_service_factory.h" | 23 #include "ios/chrome/browser/signin/authentication_service_factory.h" |
| 24 #include "ios/chrome/browser/sync/sync_setup_service.h" |
| 25 #include "ios/chrome/browser/sync/sync_setup_service_factory.h" |
| 24 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrom
e.h" | 26 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrom
e.h" |
| 25 #import "ios/chrome/browser/ui/collection_view/cells/activity_indicator_cell.h" | 27 #import "ios/chrome/browser/ui/collection_view/cells/activity_indicator_cell.h" |
| 26 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" | 28 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" |
| 27 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h
" | 29 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h
" |
| 28 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" | 30 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" |
| 29 #import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h" | 31 #import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h" |
| 30 #include "ios/chrome/browser/ui/history/history_entries_status_item.h" | 32 #include "ios/chrome/browser/ui/history/history_entries_status_item.h" |
| 31 #include "ios/chrome/browser/ui/history/history_entry.h" | 33 #include "ios/chrome/browser/ui/history/history_entry.h" |
| 32 #include "ios/chrome/browser/ui/history/history_entry_inserter.h" | 34 #include "ios/chrome/browser/ui/history/history_entry_inserter.h" |
| 33 #import "ios/chrome/browser/ui/history/history_entry_item.h" | 35 #import "ios/chrome/browser/ui/history/history_entry_item.h" |
| 34 #include "ios/chrome/browser/ui/history/history_service_facade.h" | 36 #include "ios/chrome/browser/ui/history/history_service_facade.h" |
| 35 #include "ios/chrome/browser/ui/history/history_service_facade_delegate.h" | 37 #include "ios/chrome/browser/ui/history/history_service_facade_delegate.h" |
| 36 #include "ios/chrome/browser/ui/history/history_util.h" | 38 #include "ios/chrome/browser/ui/history/history_util.h" |
| 37 #import "ios/chrome/browser/ui/url_loader.h" | 39 #import "ios/chrome/browser/ui/url_loader.h" |
| 38 #include "ios/chrome/grit/ios_strings.h" | 40 #include "ios/chrome/grit/ios_strings.h" |
| 39 #import "ios/third_party/material_components_ios/src/components/Collections/src/
MaterialCollections.h" | 41 #import "ios/third_party/material_components_ios/src/components/Collections/src/
MaterialCollections.h" |
| 40 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat
erialPalettes.h" | 42 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat
erialPalettes.h" |
| 41 #import "ios/web/public/referrer.h" | 43 #import "ios/web/public/referrer.h" |
| 42 #import "ios/web/public/web_state/context_menu_params.h" | 44 #import "ios/web/public/web_state/context_menu_params.h" |
| 43 #import "net/base/mac/url_conversions.h" | 45 #import "net/base/mac/url_conversions.h" |
| 44 #include "ui/base/l10n/l10n_util.h" | 46 #include "ui/base/l10n/l10n_util.h" |
| 45 #include "ui/base/l10n/l10n_util_mac.h" | 47 #include "ui/base/l10n/l10n_util_mac.h" |
| 46 | 48 |
| 47 namespace { | 49 namespace { |
| 50 typedef NS_ENUM(NSInteger, ItemType) { |
| 51 ItemTypeHistoryEntry = kItemTypeEnumZero, |
| 52 ItemTypeEntriesStatus, |
| 53 ItemTypeActivityIndicator, |
| 54 }; |
| 48 // Section identifier for the header (sync information) section. | 55 // Section identifier for the header (sync information) section. |
| 49 const NSInteger kEntriesStatusSectionIdentifier = kSectionIdentifierEnumZero; | 56 const NSInteger kEntriesStatusSectionIdentifier = kSectionIdentifierEnumZero; |
| 50 // Maximum number of entries to retrieve in a single query to history service. | 57 // Maximum number of entries to retrieve in a single query to history service. |
| 51 const int kMaxFetchCount = 100; | 58 const int kMaxFetchCount = 100; |
| 52 // Horizontal inset for item separators. | 59 // Horizontal inset for item separators. |
| 53 const CGFloat kSeparatorInset = 10; | 60 const CGFloat kSeparatorInset = 10; |
| 54 } | 61 } |
| 55 | 62 |
| 56 @interface HistoryCollectionViewController ()<HistoryEntriesStatusItemDelegate, | 63 @interface HistoryCollectionViewController ()<HistoryEntriesStatusItemDelegate, |
| 57 HistoryEntryInserterDelegate, | 64 HistoryEntryInserterDelegate, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 - (void)fetchHistoryForQuery:(NSString*)query | 107 - (void)fetchHistoryForQuery:(NSString*)query |
| 101 priorToTime:(const base::Time&)time; | 108 priorToTime:(const base::Time&)time; |
| 102 // Updates header section to provide relevant information about the currently | 109 // Updates header section to provide relevant information about the currently |
| 103 // displayed history entries. | 110 // displayed history entries. |
| 104 - (void)updateEntriesStatusMessage; | 111 - (void)updateEntriesStatusMessage; |
| 105 // Removes selected items from the visible collection, but does not delete them | 112 // Removes selected items from the visible collection, but does not delete them |
| 106 // from browser history. | 113 // from browser history. |
| 107 - (void)removeSelectedItemsFromCollection; | 114 - (void)removeSelectedItemsFromCollection; |
| 108 // Removes all items in the collection that are not included in entries. | 115 // Removes all items in the collection that are not included in entries. |
| 109 - (void)filterForHistoryEntries:(NSArray*)entries; | 116 - (void)filterForHistoryEntries:(NSArray*)entries; |
| 117 // Adds loading indicator to the top of the history collection, if one is not |
| 118 // already present. |
| 119 - (void)addLoadingIndicator; |
| 110 // Displays context menu on cell pressed with gestureRecognizer. | 120 // Displays context menu on cell pressed with gestureRecognizer. |
| 111 - (void)displayContextMenuInvokedByGestureRecognizer: | 121 - (void)displayContextMenuInvokedByGestureRecognizer: |
| 112 (UILongPressGestureRecognizer*)gestureRecognizer; | 122 (UILongPressGestureRecognizer*)gestureRecognizer; |
| 113 // Opens URL in the current tab and dismisses the history view. | 123 // Opens URL in the current tab and dismisses the history view. |
| 114 - (void)openURL:(const GURL&)URL; | 124 - (void)openURL:(const GURL&)URL; |
| 115 // Opens URL in a new non-incognito tab and dismisses the history view. | 125 // Opens URL in a new non-incognito tab and dismisses the history view. |
| 116 - (void)openURLInNewTab:(const GURL&)URL; | 126 - (void)openURLInNewTab:(const GURL&)URL; |
| 117 // Opens URL in a new incognito tab and dismisses the history view. | 127 // Opens URL in a new incognito tab and dismisses the history view. |
| 118 - (void)openURLInNewIncognitoTab:(const GURL&)URL; | 128 - (void)openURLInNewIncognitoTab:(const GURL&)URL; |
| 119 // Copies URL to the clipboard. | 129 // Copies URL to the clipboard. |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 inSectionWithIdentifier: | 318 inSectionWithIdentifier: |
| 309 [self.entryInserter sectionIdentifierForTimestamp:item.timestamp]]; | 319 [self.entryInserter sectionIdentifierForTimestamp:item.timestamp]]; |
| 310 } | 320 } |
| 311 } | 321 } |
| 312 | 322 |
| 313 #pragma mark - HistoryServiceFacadeDelegate | 323 #pragma mark - HistoryServiceFacadeDelegate |
| 314 | 324 |
| 315 - (void)historyServiceFacade:(HistoryServiceFacade*)facade | 325 - (void)historyServiceFacade:(HistoryServiceFacade*)facade |
| 316 didReceiveQueryResult:(HistoryServiceFacade::QueryResult)result { | 326 didReceiveQueryResult:(HistoryServiceFacade::QueryResult)result { |
| 317 self.loading = NO; | 327 self.loading = NO; |
| 318 // Remove loading indicator. | 328 // If history sync is enabled and there hasn't been a response from synced |
| 319 CollectionViewItem* headerItem = [self.collectionViewModel | 329 // history, try fetching again. |
| 320 itemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; | 330 SyncSetupService* syncSetupService = |
| 321 if ([headerItem.cellClass isSubclassOfClass:[ActivityIndicatorCell class]]) { | 331 SyncSetupServiceFactory::GetForBrowserState(_browserState); |
| 322 [self.collectionViewModel removeItemWithType:kItemTypeEnumZero | 332 if (syncSetupService->IsSyncEnabled() && |
| 323 fromSectionWithIdentifier:kSectionIdentifierEnumZero]; | 333 syncSetupService->IsDataTypeEnabled(syncer::HISTORY_DELETE_DIRECTIVES) && |
| 324 [self.collectionView | 334 !result.sync_returned) { |
| 325 deleteItemsAtIndexPaths:@[ [NSIndexPath indexPathForItem:0 | 335 [self showHistoryMatchingQuery:_currentQuery]; |
| 326 inSection:0] ]]; | 336 return; |
| 327 } | 337 } |
| 328 | 338 |
| 329 // If there are no results and no URLs have been loaded, report that no | 339 // If there are no results and no URLs have been loaded, report that no |
| 330 // history entries were found. | 340 // history entries were found. |
| 331 if (result.entries.empty() && !self.hasHistoryEntries) { | 341 if (result.entries.empty() && !self.hasHistoryEntries) { |
| 332 DCHECK(self.entriesType == NO_ENTRIES); | 342 DCHECK(self.entriesType == NO_ENTRIES); |
| 333 [self updateEntriesStatusMessage]; | 343 [self updateEntriesStatusMessage]; |
| 334 [self.delegate historyCollectionViewControllerDidChangeEntries:self]; | 344 [self.delegate historyCollectionViewControllerDidChangeEntries:self]; |
| 335 return; | 345 return; |
| 336 } | 346 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 347 | 357 |
| 348 __block base::scoped_nsobject<NSMutableArray> searchResults( | 358 __block base::scoped_nsobject<NSMutableArray> searchResults( |
| 349 [[NSMutableArray array] retain]); | 359 [[NSMutableArray array] retain]); |
| 350 __block base::scoped_nsobject<NSString> searchQuery( | 360 __block base::scoped_nsobject<NSString> searchQuery( |
| 351 [base::SysUTF16ToNSString(result.query) copy]); | 361 [base::SysUTF16ToNSString(result.query) copy]); |
| 352 [self.collectionView performBatchUpdates:^{ | 362 [self.collectionView performBatchUpdates:^{ |
| 353 // There should always be at least a header section present. | 363 // There should always be at least a header section present. |
| 354 DCHECK([[self collectionViewModel] numberOfSections]); | 364 DCHECK([[self collectionViewModel] numberOfSections]); |
| 355 for (const history::HistoryEntry& entry : entries) { | 365 for (const history::HistoryEntry& entry : entries) { |
| 356 HistoryEntryItem* item = | 366 HistoryEntryItem* item = |
| 357 [[[HistoryEntryItem alloc] initWithType:kItemTypeEnumZero | 367 [[[HistoryEntryItem alloc] initWithType:ItemTypeHistoryEntry |
| 358 historyEntry:entry | 368 historyEntry:entry |
| 359 browserState:_browserState | 369 browserState:_browserState |
| 360 delegate:self] autorelease]; | 370 delegate:self] autorelease]; |
| 361 [self.entryInserter insertHistoryEntryItem:item]; | 371 [self.entryInserter insertHistoryEntryItem:item]; |
| 362 if ([self isSearching]) { | 372 if ([self isSearching]) { |
| 363 [searchResults addObject:item]; | 373 [searchResults addObject:item]; |
| 364 } | 374 } |
| 365 } | 375 } |
| 366 [self.delegate historyCollectionViewControllerDidChangeEntries:self]; | 376 [self.delegate historyCollectionViewControllerDidChangeEntries:self]; |
| 367 } | 377 } |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 [self.collectionViewModel itemAtIndexPath:indexPath]); | 529 [self.collectionViewModel itemAtIndexPath:indexPath]); |
| 520 [self fetchHistoryForQuery:_currentQuery priorToTime:lastItem.timestamp]; | 530 [self fetchHistoryForQuery:_currentQuery priorToTime:lastItem.timestamp]; |
| 521 } | 531 } |
| 522 } | 532 } |
| 523 | 533 |
| 524 #pragma mark - Private methods | 534 #pragma mark - Private methods |
| 525 | 535 |
| 526 - (void)fetchHistoryForQuery:(NSString*)query | 536 - (void)fetchHistoryForQuery:(NSString*)query |
| 527 priorToTime:(const base::Time&)time { | 537 priorToTime:(const base::Time&)time { |
| 528 self.loading = YES; | 538 self.loading = YES; |
| 529 // Add loading indicator if nothing else is shown. | 539 // Add loading indicator if no items are shown. |
| 530 if (!self.hasHistoryEntries && !self.isSearching) { | 540 if (!self.hasHistoryEntries && !self.isSearching) { |
| 531 [self.collectionView performBatchUpdates:^{ | 541 [self addLoadingIndicator]; |
| 532 NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; | |
| 533 if ([self.collectionViewModel hasItemAtIndexPath:indexPath]) { | |
| 534 [self.collectionViewModel | |
| 535 removeItemWithType:kItemTypeEnumZero | |
| 536 fromSectionWithIdentifier:kSectionIdentifierEnumZero]; | |
| 537 [self.collectionView deleteItemsAtIndexPaths:@[ indexPath ]]; | |
| 538 } | |
| 539 CollectionViewItem* loadingIndicatorItem = [[[CollectionViewItem alloc] | |
| 540 initWithType:kItemTypeEnumZero] autorelease]; | |
| 541 loadingIndicatorItem.cellClass = [ActivityIndicatorCell class]; | |
| 542 [self.collectionViewModel addItem:loadingIndicatorItem | |
| 543 toSectionWithIdentifier:kEntriesStatusSectionIdentifier]; | |
| 544 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; | |
| 545 } | |
| 546 completion:nil]; | |
| 547 } | 542 } |
| 548 | 543 |
| 549 BOOL fetchAllHistory = !query || [query isEqualToString:@""]; | 544 BOOL fetchAllHistory = !query || [query isEqualToString:@""]; |
| 550 base::string16 queryString = | 545 base::string16 queryString = |
| 551 fetchAllHistory ? base::string16() : base::SysNSStringToUTF16(query); | 546 fetchAllHistory ? base::string16() : base::SysNSStringToUTF16(query); |
| 552 history::QueryOptions options; | 547 history::QueryOptions options; |
| 553 options.end_time = time; | 548 options.end_time = time; |
| 554 options.duplicate_policy = | 549 options.duplicate_policy = |
| 555 fetchAllHistory ? history::QueryOptions::REMOVE_DUPLICATES_PER_DAY | 550 fetchAllHistory ? history::QueryOptions::REMOVE_DUPLICATES_PER_DAY |
| 556 : history::QueryOptions::REMOVE_ALL_DUPLICATES; | 551 : history::QueryOptions::REMOVE_ALL_DUPLICATES; |
| 557 options.max_count = kMaxFetchCount; | 552 options.max_count = kMaxFetchCount; |
| 558 options.matching_algorithm = | 553 options.matching_algorithm = |
| 559 query_parser::MatchingAlgorithm::ALWAYS_PREFIX_SEARCH; | 554 query_parser::MatchingAlgorithm::ALWAYS_PREFIX_SEARCH; |
| 560 _historyServiceFacade->QueryOtherFormsOfBrowsingHistory(); | |
| 561 _historyServiceFacade->QueryHistory(queryString, options); | 555 _historyServiceFacade->QueryHistory(queryString, options); |
| 562 // Also determine whether notice regarding other forms of browsing history | 556 // Also determine whether notice regarding other forms of browsing history |
| 563 // should be shown. | 557 // should be shown. |
| 564 _historyServiceFacade->QueryOtherFormsOfBrowsingHistory(); | 558 _historyServiceFacade->QueryOtherFormsOfBrowsingHistory(); |
| 565 } | 559 } |
| 566 | 560 |
| 567 - (void)updateEntriesStatusMessage { | 561 - (void)updateEntriesStatusMessage { |
| 568 CollectionViewItem* entriesStatusItem = nil; | 562 CollectionViewItem* entriesStatusItem = nil; |
| 569 if (!self.hasHistoryEntries) { | 563 if (!self.hasHistoryEntries) { |
| 570 CollectionViewTextItem* noResultsItem = [[[CollectionViewTextItem alloc] | 564 CollectionViewTextItem* noResultsItem = [[[CollectionViewTextItem alloc] |
| 571 initWithType:kItemTypeEnumZero] autorelease]; | 565 initWithType:ItemTypeEntriesStatus] autorelease]; |
| 572 noResultsItem.text = | 566 noResultsItem.text = |
| 573 self.isSearching ? l10n_util::GetNSString(IDS_HISTORY_NO_SEARCH_RESULTS) | 567 self.isSearching ? l10n_util::GetNSString(IDS_HISTORY_NO_SEARCH_RESULTS) |
| 574 : l10n_util::GetNSString(IDS_HISTORY_NO_RESULTS); | 568 : l10n_util::GetNSString(IDS_HISTORY_NO_RESULTS); |
| 575 entriesStatusItem = noResultsItem; | 569 entriesStatusItem = noResultsItem; |
| 576 } else { | 570 } else { |
| 577 HistoryEntriesStatusItem* historyEntriesStatusItem = | 571 HistoryEntriesStatusItem* historyEntriesStatusItem = |
| 578 [[[HistoryEntriesStatusItem alloc] initWithType:kItemTypeEnumZero] | 572 [[[HistoryEntriesStatusItem alloc] initWithType:ItemTypeEntriesStatus] |
| 579 autorelease]; | 573 autorelease]; |
| 580 historyEntriesStatusItem.delegate = self; | 574 historyEntriesStatusItem.delegate = self; |
| 581 AuthenticationService* authService = | 575 AuthenticationService* authService = |
| 582 AuthenticationServiceFactory::GetForBrowserState(_browserState); | 576 AuthenticationServiceFactory::GetForBrowserState(_browserState); |
| 583 BOOL signedIn = authService->IsAuthenticated(); | 577 BOOL signedIn = authService->IsAuthenticated(); |
| 584 | 578 |
| 585 historyEntriesStatusItem.hidden = | 579 historyEntriesStatusItem.hidden = |
| 586 self.isSearching || (!signedIn && self.hasHistoryEntries); | 580 self.isSearching || (!signedIn && self.hasHistoryEntries); |
| 587 historyEntriesStatusItem.entriesStatus = self.entriesType; | 581 historyEntriesStatusItem.entriesStatus = self.entriesType; |
| 588 historyEntriesStatusItem.showsOtherBrowsingDataNotice = | 582 historyEntriesStatusItem.showsOtherBrowsingDataNotice = |
| 589 _shouldShowNoticeAboutOtherFormsOfBrowsingHistory; | 583 _shouldShowNoticeAboutOtherFormsOfBrowsingHistory; |
| 590 entriesStatusItem = historyEntriesStatusItem; | 584 entriesStatusItem = historyEntriesStatusItem; |
| 591 } | 585 } |
| 592 // Replace the item in the first section, which is always present. | 586 // Replace the item in the first section, which is always present. |
| 593 NSArray* items = [self.collectionViewModel | 587 NSArray* items = [self.collectionViewModel |
| 594 itemsInSectionWithIdentifier:kEntriesStatusSectionIdentifier]; | 588 itemsInSectionWithIdentifier:kEntriesStatusSectionIdentifier]; |
| 595 if ([items count]) { | 589 if ([items count]) { |
| 596 // There should only ever be one item in this section. | 590 // There should only ever be one item in this section. |
| 597 DCHECK([items count] == 1); | 591 DCHECK([items count] == 1); |
| 598 // Only update if the item has changed. | 592 // Only update if the item has changed. |
| 599 if ([items[0] isEqual:entriesStatusItem]) { | 593 if ([items[0] isEqual:entriesStatusItem]) { |
| 600 return; | 594 return; |
| 601 } | 595 } |
| 602 } | 596 } |
| 603 [self.collectionView performBatchUpdates:^{ | 597 [self.collectionView performBatchUpdates:^{ |
| 604 NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; | 598 NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; |
| 605 if ([items count]) { | 599 if ([items count]) { |
| 606 [self.collectionViewModel | 600 [self.collectionViewModel |
| 607 removeItemWithType:kItemTypeEnumZero | 601 removeItemWithType:[self.collectionViewModel |
| 602 itemTypeForIndexPath:indexPath] |
| 608 fromSectionWithIdentifier:kEntriesStatusSectionIdentifier]; | 603 fromSectionWithIdentifier:kEntriesStatusSectionIdentifier]; |
| 609 [self.collectionView deleteItemsAtIndexPaths:@[ indexPath ]]; | 604 [self.collectionView deleteItemsAtIndexPaths:@[ indexPath ]]; |
| 610 } | 605 } |
| 611 [self.collectionViewModel addItem:entriesStatusItem | 606 [self.collectionViewModel addItem:entriesStatusItem |
| 612 toSectionWithIdentifier:kEntriesStatusSectionIdentifier]; | 607 toSectionWithIdentifier:kEntriesStatusSectionIdentifier]; |
| 613 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; | 608 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; |
| 614 } | 609 } |
| 615 completion:nil]; | 610 completion:nil]; |
| 616 } | 611 } |
| 617 | 612 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 selectItemAtIndexPath:indexPath | 655 selectItemAtIndexPath:indexPath |
| 661 animated:NO | 656 animated:NO |
| 662 scrollPosition:UICollectionViewScrollPositionNone]; | 657 scrollPosition:UICollectionViewScrollPositionNone]; |
| 663 } | 658 } |
| 664 } | 659 } |
| 665 } | 660 } |
| 666 } | 661 } |
| 667 [self removeSelectedItemsFromCollection]; | 662 [self removeSelectedItemsFromCollection]; |
| 668 } | 663 } |
| 669 | 664 |
| 665 - (void)addLoadingIndicator { |
| 666 NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; |
| 667 if ([self.collectionViewModel hasItemAtIndexPath:indexPath] && |
| 668 [self.collectionViewModel itemTypeForIndexPath:indexPath] == |
| 669 ItemTypeActivityIndicator) { |
| 670 // Do not add indicator a second time. |
| 671 return; |
| 672 } |
| 673 |
| 674 [self.collectionView performBatchUpdates:^{ |
| 675 if ([self.collectionViewModel hasItemAtIndexPath:indexPath]) { |
| 676 [self.collectionViewModel |
| 677 removeItemWithType:[self.collectionViewModel |
| 678 itemTypeForIndexPath:indexPath] |
| 679 fromSectionWithIdentifier:kSectionIdentifierEnumZero]; |
| 680 [self.collectionView deleteItemsAtIndexPaths:@[ indexPath ]]; |
| 681 } |
| 682 CollectionViewItem* loadingIndicatorItem = [[[CollectionViewItem alloc] |
| 683 initWithType:ItemTypeActivityIndicator] autorelease]; |
| 684 loadingIndicatorItem.cellClass = [ActivityIndicatorCell class]; |
| 685 [self.collectionViewModel addItem:loadingIndicatorItem |
| 686 toSectionWithIdentifier:kEntriesStatusSectionIdentifier]; |
| 687 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; |
| 688 } |
| 689 completion:nil]; |
| 690 } |
| 691 |
| 670 #pragma mark Context Menu | 692 #pragma mark Context Menu |
| 671 | 693 |
| 672 - (void)displayContextMenuInvokedByGestureRecognizer: | 694 - (void)displayContextMenuInvokedByGestureRecognizer: |
| 673 (UILongPressGestureRecognizer*)gestureRecognizer { | 695 (UILongPressGestureRecognizer*)gestureRecognizer { |
| 674 if (gestureRecognizer.numberOfTouches != 1 || self.editing || | 696 if (gestureRecognizer.numberOfTouches != 1 || self.editing || |
| 675 gestureRecognizer.state != UIGestureRecognizerStateBegan) { | 697 gestureRecognizer.state != UIGestureRecognizerStateBegan) { |
| 676 return; | 698 return; |
| 677 } | 699 } |
| 678 | 700 |
| 679 CGPoint touchLocation = | 701 CGPoint touchLocation = |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 NSData* plainText = [base::SysUTF8ToNSString(URL.spec()) | 804 NSData* plainText = [base::SysUTF8ToNSString(URL.spec()) |
| 783 dataUsingEncoding:NSUTF8StringEncoding]; | 805 dataUsingEncoding:NSUTF8StringEncoding]; |
| 784 NSDictionary* copiedItem = @{ | 806 NSDictionary* copiedItem = @{ |
| 785 (NSString*)kUTTypeURL : net::NSURLWithGURL(URL), | 807 (NSString*)kUTTypeURL : net::NSURLWithGURL(URL), |
| 786 (NSString*)kUTTypeUTF8PlainText : plainText, | 808 (NSString*)kUTTypeUTF8PlainText : plainText, |
| 787 }; | 809 }; |
| 788 [[UIPasteboard generalPasteboard] setItems:@[ copiedItem ]]; | 810 [[UIPasteboard generalPasteboard] setItems:@[ copiedItem ]]; |
| 789 } | 811 } |
| 790 | 812 |
| 791 @end | 813 @end |
| OLD | NEW |