OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 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 #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" | 5 #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/hash.h" | 12 #include "base/hash.h" |
13 #include "base/i18n/string_compare.h" | 13 #include "base/i18n/string_compare.h" |
14 #include "base/mac/bind_objc_block.h" | 14 #include "base/mac/bind_objc_block.h" |
15 #include "base/mac/scoped_nsautorelease_pool.h" | |
16 #include "base/mac/scoped_nsobject.h" | |
17 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
18 #include "base/metrics/user_metrics_action.h" | 16 #include "base/metrics/user_metrics_action.h" |
19 #include "base/strings/sys_string_conversions.h" | 17 #include "base/strings/sys_string_conversions.h" |
20 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
21 #include "components/bookmarks/browser/bookmark_model.h" | 19 #include "components/bookmarks/browser/bookmark_model.h" |
22 #include "components/query_parser/query_parser.h" | 20 #include "components/query_parser/query_parser.h" |
23 #include "components/strings/grit/components_strings.h" | 21 #include "components/strings/grit/components_strings.h" |
24 #include "ios/chrome/browser/bookmarks/bookmarks_utils.h" | 22 #include "ios/chrome/browser/bookmarks/bookmarks_utils.h" |
25 #include "ios/chrome/browser/experimental_flags.h" | 23 #include "ios/chrome/browser/experimental_flags.h" |
26 #import "ios/chrome/browser/ui/bookmarks/bookmark_collection_cells.h" | 24 #import "ios/chrome/browser/ui/bookmarks/bookmark_collection_cells.h" |
27 #import "ios/chrome/browser/ui/bookmarks/bookmark_menu_item.h" | 25 #import "ios/chrome/browser/ui/bookmarks/bookmark_menu_item.h" |
28 #import "ios/chrome/browser/ui/bookmarks/bookmark_position_cache.h" | 26 #import "ios/chrome/browser/ui/bookmarks/bookmark_position_cache.h" |
29 #include "ios/chrome/browser/ui/bookmarks/undo_manager_wrapper.h" | 27 #include "ios/chrome/browser/ui/bookmarks/undo_manager_wrapper.h" |
30 #include "ios/chrome/browser/ui/ui_util.h" | 28 #include "ios/chrome/browser/ui/ui_util.h" |
31 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 29 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
32 #include "ios/chrome/grit/ios_strings.h" | 30 #include "ios/chrome/grit/ios_strings.h" |
33 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat
erialSnackbar.h" | 31 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat
erialSnackbar.h" |
34 #include "third_party/skia/include/core/SkColor.h" | 32 #include "third_party/skia/include/core/SkColor.h" |
35 #include "ui/base/l10n/l10n_util.h" | 33 #include "ui/base/l10n/l10n_util.h" |
36 #include "ui/base/l10n/l10n_util_mac.h" | 34 #include "ui/base/l10n/l10n_util_mac.h" |
37 #include "ui/base/models/tree_node_iterator.h" | 35 #include "ui/base/models/tree_node_iterator.h" |
38 | 36 |
| 37 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 38 #error "This file requires ARC support." |
| 39 #endif |
| 40 |
39 using bookmarks::BookmarkNode; | 41 using bookmarks::BookmarkNode; |
40 | 42 |
41 namespace bookmark_utils_ios { | 43 namespace bookmark_utils_ios { |
42 | 44 |
43 namespace { | 45 namespace { |
44 | 46 |
45 const BookmarkNode* FindFolderById(bookmarks::BookmarkModel* model, | 47 const BookmarkNode* FindFolderById(bookmarks::BookmarkModel* model, |
46 int64_t id) { | 48 int64_t id) { |
47 ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); | 49 ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); |
48 while (iterator.has_next()) { | 50 while (iterator.has_next()) { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 return CGRectGetWidth(statusBarWindowRect); | 182 return CGRectGetWidth(statusBarWindowRect); |
181 } | 183 } |
182 } | 184 } |
183 | 185 |
184 BOOL bookmarkMenuIsInSlideInPanel() { | 186 BOOL bookmarkMenuIsInSlideInPanel() { |
185 return !IsIPadIdiom() || IsCompactTablet(); | 187 return !IsIPadIdiom() || IsCompactTablet(); |
186 } | 188 } |
187 | 189 |
188 UIView* dropShadowWithWidth(CGFloat width) { | 190 UIView* dropShadowWithWidth(CGFloat width) { |
189 UIImage* shadowImage = [UIImage imageNamed:@"bookmark_bar_shadow"]; | 191 UIImage* shadowImage = [UIImage imageNamed:@"bookmark_bar_shadow"]; |
190 UIImageView* shadow = | 192 UIImageView* shadow = [[UIImageView alloc] initWithImage:shadowImage]; |
191 [[[UIImageView alloc] initWithImage:shadowImage] autorelease]; | |
192 CGRect shadowFrame = CGRectMake(0, 0, width, 4); | 193 CGRect shadowFrame = CGRectMake(0, 0, width, 4); |
193 shadow.frame = shadowFrame; | 194 shadow.frame = shadowFrame; |
194 shadow.autoresizingMask = | 195 shadow.autoresizingMask = |
195 UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth; | 196 UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth; |
196 return shadow; | 197 return shadow; |
197 } | 198 } |
198 | 199 |
199 #pragma mark - Updating Bookmarks | 200 #pragma mark - Updating Bookmarks |
200 | 201 |
201 // Deletes all subnodes of |node|, including |node|, that are in |bookmarks|. | 202 // Deletes all subnodes of |node|, including |node|, that are in |bookmarks|. |
(...skipping 16 matching lines...) Expand all Loading... |
218 DCHECK(!node || node->is_url()); | 219 DCHECK(!node || node->is_url()); |
219 base::string16 titleString = base::SysNSStringToUTF16(title); | 220 base::string16 titleString = base::SysNSStringToUTF16(title); |
220 | 221 |
221 // If the bookmark has no changes supporting Undo, just bail out. | 222 // If the bookmark has no changes supporting Undo, just bail out. |
222 if (node && node->GetTitle() == titleString && node->url() == url && | 223 if (node && node->GetTitle() == titleString && node->url() == url && |
223 node->parent() == folder) { | 224 node->parent() == folder) { |
224 return; | 225 return; |
225 } | 226 } |
226 | 227 |
227 // Secondly, create an Undo group for all undoable actions. | 228 // Secondly, create an Undo group for all undoable actions. |
228 base::scoped_nsobject<UndoManagerWrapper> wrapper( | 229 UndoManagerWrapper* wrapper = |
229 [[UndoManagerWrapper alloc] initWithBrowserState:browser_state]); | 230 [[UndoManagerWrapper alloc] initWithBrowserState:browser_state]; |
230 | 231 |
231 // Create or update the bookmark. | 232 // Create or update the bookmark. |
232 [wrapper startGroupingActions]; | 233 [wrapper startGroupingActions]; |
233 | 234 |
234 // Save the bookmark information. | 235 // Save the bookmark information. |
235 if (!node) { // Create a new bookmark. | 236 if (!node) { // Create a new bookmark. |
236 bookmark_model->client()->RecordAction( | 237 bookmark_model->client()->RecordAction( |
237 base::UserMetricsAction("BookmarkAdded")); | 238 base::UserMetricsAction("BookmarkAdded")); |
238 node = | 239 node = |
239 bookmark_model->AddURL(folder, folder->child_count(), titleString, url); | 240 bookmark_model->AddURL(folder, folder->child_count(), titleString, url); |
(...skipping 13 matching lines...) Expand all Loading... |
253 [wrapper resetUndoManagerChanged]; | 254 [wrapper resetUndoManagerChanged]; |
254 | 255 |
255 NSString* text = | 256 NSString* text = |
256 l10n_util::GetNSString((node) ? IDS_IOS_BOOKMARK_NEW_BOOKMARK_UPDATED | 257 l10n_util::GetNSString((node) ? IDS_IOS_BOOKMARK_NEW_BOOKMARK_UPDATED |
257 : IDS_IOS_BOOKMARK_NEW_BOOKMARK_CREATED); | 258 : IDS_IOS_BOOKMARK_NEW_BOOKMARK_CREATED); |
258 PresentUndoToastWithWrapper(wrapper, text); | 259 PresentUndoToastWithWrapper(wrapper, text); |
259 } | 260 } |
260 | 261 |
261 void PresentUndoToastWithWrapper(UndoManagerWrapper* wrapper, NSString* text) { | 262 void PresentUndoToastWithWrapper(UndoManagerWrapper* wrapper, NSString* text) { |
262 // Create the block that will be executed if the user taps the undo button. | 263 // Create the block that will be executed if the user taps the undo button. |
263 MDCSnackbarMessageAction* action = | 264 MDCSnackbarMessageAction* action = [[MDCSnackbarMessageAction alloc] init]; |
264 [[[MDCSnackbarMessageAction alloc] init] autorelease]; | |
265 action.handler = ^{ | 265 action.handler = ^{ |
266 if (![wrapper hasUndoManagerChanged]) | 266 if (![wrapper hasUndoManagerChanged]) |
267 [wrapper undo]; | 267 [wrapper undo]; |
268 }; | 268 }; |
269 | 269 |
270 action.title = l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_UNDO_BUTTON_TITLE); | 270 action.title = l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_UNDO_BUTTON_TITLE); |
271 action.accessibilityIdentifier = @"Undo"; | 271 action.accessibilityIdentifier = @"Undo"; |
272 action.accessibilityLabel = | 272 action.accessibilityLabel = |
273 l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_UNDO_BUTTON_TITLE); | 273 l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_UNDO_BUTTON_TITLE); |
274 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); | 274 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); |
(...skipping 20 matching lines...) Expand all Loading... |
295 if (bookmarks.find(node) != bookmarks.end()) | 295 if (bookmarks.find(node) != bookmarks.end()) |
296 model->Remove(node); | 296 model->Remove(node); |
297 } | 297 } |
298 | 298 |
299 void DeleteBookmarksWithUndoToast(const std::set<const BookmarkNode*>& nodes, | 299 void DeleteBookmarksWithUndoToast(const std::set<const BookmarkNode*>& nodes, |
300 bookmarks::BookmarkModel* model, | 300 bookmarks::BookmarkModel* model, |
301 ios::ChromeBrowserState* browser_state) { | 301 ios::ChromeBrowserState* browser_state) { |
302 size_t nodeCount = nodes.size(); | 302 size_t nodeCount = nodes.size(); |
303 DCHECK_GT(nodeCount, 0u); | 303 DCHECK_GT(nodeCount, 0u); |
304 | 304 |
305 base::scoped_nsobject<UndoManagerWrapper> wrapper( | 305 UndoManagerWrapper* wrapper = |
306 [[UndoManagerWrapper alloc] initWithBrowserState:browser_state]); | 306 [[UndoManagerWrapper alloc] initWithBrowserState:browser_state]; |
307 | 307 |
308 // Delete the selected bookmarks. | 308 // Delete the selected bookmarks. |
309 [wrapper startGroupingActions]; | 309 [wrapper startGroupingActions]; |
310 bookmark_utils_ios::DeleteBookmarks(nodes, model); | 310 bookmark_utils_ios::DeleteBookmarks(nodes, model); |
311 [wrapper stopGroupingActions]; | 311 [wrapper stopGroupingActions]; |
312 [wrapper resetUndoManagerChanged]; | 312 [wrapper resetUndoManagerChanged]; |
313 | 313 |
314 NSString* text = nil; | 314 NSString* text = nil; |
315 | 315 |
316 if (nodeCount == 1) { | 316 if (nodeCount == 1) { |
(...skipping 30 matching lines...) Expand all Loading... |
347 return didPerformMove; | 347 return didPerformMove; |
348 } | 348 } |
349 | 349 |
350 void MoveBookmarksWithUndoToast(const std::set<const BookmarkNode*>& nodes, | 350 void MoveBookmarksWithUndoToast(const std::set<const BookmarkNode*>& nodes, |
351 bookmarks::BookmarkModel* model, | 351 bookmarks::BookmarkModel* model, |
352 const BookmarkNode* folder, | 352 const BookmarkNode* folder, |
353 ios::ChromeBrowserState* browser_state) { | 353 ios::ChromeBrowserState* browser_state) { |
354 size_t nodeCount = nodes.size(); | 354 size_t nodeCount = nodes.size(); |
355 DCHECK_GT(nodeCount, 0u); | 355 DCHECK_GT(nodeCount, 0u); |
356 | 356 |
357 base::scoped_nsobject<UndoManagerWrapper> wrapper( | 357 UndoManagerWrapper* wrapper = |
358 [[UndoManagerWrapper alloc] initWithBrowserState:browser_state]); | 358 [[UndoManagerWrapper alloc] initWithBrowserState:browser_state]; |
359 | 359 |
360 // Move the selected bookmarks. | 360 // Move the selected bookmarks. |
361 [wrapper startGroupingActions]; | 361 [wrapper startGroupingActions]; |
362 bool didPerformMove = bookmark_utils_ios::MoveBookmarks(nodes, model, folder); | 362 bool didPerformMove = bookmark_utils_ios::MoveBookmarks(nodes, model, folder); |
363 [wrapper stopGroupingActions]; | 363 [wrapper stopGroupingActions]; |
364 [wrapper resetUndoManagerChanged]; | 364 [wrapper resetUndoManagerChanged]; |
365 | 365 |
366 if (!didPerformMove) | 366 if (!didPerformMove) |
367 return; // Don't present a snackbar when no real move as happened. | 367 return; // Don't present a snackbar when no real move as happened. |
368 | 368 |
(...skipping 28 matching lines...) Expand all Loading... |
397 NodesSection::NodesSection() {} | 397 NodesSection::NodesSection() {} |
398 | 398 |
399 NodesSection::~NodesSection() {} | 399 NodesSection::~NodesSection() {} |
400 | 400 |
401 void segregateNodes( | 401 void segregateNodes( |
402 const NodeVector& vector, | 402 const NodeVector& vector, |
403 std::vector<std::unique_ptr<NodesSection>>& nodesSectionVector) { | 403 std::vector<std::unique_ptr<NodesSection>>& nodesSectionVector) { |
404 nodesSectionVector.clear(); | 404 nodesSectionVector.clear(); |
405 | 405 |
406 // Make a localized date formatter. | 406 // Make a localized date formatter. |
407 base::scoped_nsobject<NSDateFormatter> formatter( | 407 NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; |
408 [[NSDateFormatter alloc] init]); | |
409 [formatter setDateFormat:@"MMMM yyyy"]; | 408 [formatter setDateFormat:@"MMMM yyyy"]; |
410 // Segregate nodes by creation date. | 409 // Segregate nodes by creation date. |
411 // Nodes that were created in the same month are grouped together. | 410 // Nodes that were created in the same month are grouped together. |
412 for (auto* node : vector) { | 411 for (auto* node : vector) { |
413 base::mac::ScopedNSAutoreleasePool pool; | 412 @autoreleasepool { |
414 base::Time dateAdded = node->date_added(); | 413 base::Time dateAdded = node->date_added(); |
415 base::TimeDelta delta = dateAdded - base::Time::UnixEpoch(); | 414 base::TimeDelta delta = dateAdded - base::Time::UnixEpoch(); |
416 base::scoped_nsobject<NSDate> date( | 415 NSDate* date = |
417 [[NSDate alloc] initWithTimeIntervalSince1970:delta.InSeconds()]); | 416 [[NSDate alloc] initWithTimeIntervalSince1970:delta.InSeconds()]; |
418 NSString* dateString = [formatter stringFromDate:date]; | 417 NSString* dateString = [formatter stringFromDate:date]; |
419 const std::string timeRepresentation = base::SysNSStringToUTF8(dateString); | 418 const std::string timeRepresentation = |
| 419 base::SysNSStringToUTF8(dateString); |
420 | 420 |
421 BOOL found = NO; | 421 BOOL found = NO; |
422 for (const auto& nodesSection : nodesSectionVector) { | 422 for (const auto& nodesSection : nodesSectionVector) { |
423 if (nodesSection->timeRepresentation == timeRepresentation) { | 423 if (nodesSection->timeRepresentation == timeRepresentation) { |
424 nodesSection->vector.push_back(node); | 424 nodesSection->vector.push_back(node); |
425 found = YES; | 425 found = YES; |
426 break; | 426 break; |
| 427 } |
427 } | 428 } |
| 429 |
| 430 if (found) |
| 431 continue; |
| 432 |
| 433 // No NodesSection found. |
| 434 auto nodesSection = base::MakeUnique<NodesSection>(); |
| 435 nodesSection->time = dateAdded; |
| 436 nodesSection->timeRepresentation = timeRepresentation; |
| 437 nodesSection->vector.push_back(node); |
| 438 nodesSectionVector.push_back(std::move(nodesSection)); |
428 } | 439 } |
429 | |
430 if (found) | |
431 continue; | |
432 | |
433 // No NodesSection found. | |
434 auto nodesSection = base::MakeUnique<NodesSection>(); | |
435 nodesSection->time = dateAdded; | |
436 nodesSection->timeRepresentation = timeRepresentation; | |
437 nodesSection->vector.push_back(node); | |
438 nodesSectionVector.push_back(std::move(nodesSection)); | |
439 } | 440 } |
440 | 441 |
441 // Sort the NodesSections. | 442 // Sort the NodesSections. |
442 std::sort(nodesSectionVector.begin(), nodesSectionVector.end(), | 443 std::sort(nodesSectionVector.begin(), nodesSectionVector.end(), |
443 [](const std::unique_ptr<NodesSection>& n1, | 444 [](const std::unique_ptr<NodesSection>& n1, |
444 const std::unique_ptr<NodesSection>& n2) { | 445 const std::unique_ptr<NodesSection>& n2) { |
445 return n1->time > n2->time; | 446 return n1->time > n2->time; |
446 }); | 447 }); |
447 | 448 |
448 // For each NodesSection, sort the nodes inside. | 449 // For each NodesSection, sort the nodes inside. |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 | 677 |
677 *position = cache.position; | 678 *position = cache.position; |
678 return YES; | 679 return YES; |
679 } | 680 } |
680 | 681 |
681 void ClearPositionCache() { | 682 void ClearPositionCache() { |
682 [[NSUserDefaults standardUserDefaults] removeObjectForKey:kPositionCacheKey]; | 683 [[NSUserDefaults standardUserDefaults] removeObjectForKey:kPositionCacheKey]; |
683 } | 684 } |
684 | 685 |
685 } // namespace bookmark_utils_ios | 686 } // namespace bookmark_utils_ios |
OLD | NEW |