From 709568797110fce0e5eb2ca4badb9ad17f40b845 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Apr 2026 04:06:53 +0000 Subject: [PATCH 1/2] Polish gallery sort: standard icon, native menu with checkmarks - Use arrow.up.arrow.down (the conventional iOS sort glyph) instead of text.line.magnify, which reads as a search/zoom affordance. - Replace the action sheet (which marked the active option with an ASCII "--> " prefix) with a UIMenu using .singleSelection. The current sort now renders with a native checkmark. UIDeferredMenuElement.uncached rebuilds the menu on each open so the indicator always reflects the latest selection. https://claude.ai/code/session_01RRD9boKycR1JgTi9NkZKRF --- BeeSwift/Gallery/GalleryViewController.swift | 35 ++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index 5a6bd921..ba478e50 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -171,10 +171,8 @@ class GalleryViewController: UIViewController { action: #selector(self.settingsButtonPressed) ), UIBarButtonItem( - image: UIImage(systemName: "text.line.magnify"), - style: UIBarButtonItem.Style.plain, - target: self, - action: #selector(self.pickSortTapped) + image: UIImage(systemName: "arrow.up.arrow.down"), + menu: self.sortMenu() ), ] stackView.addArrangedSubview(self.freshnessIndicator) @@ -456,24 +454,27 @@ extension GalleryViewController: SFSafariViewControllerDelegate { controller.dismiss(animated: true, completion: nil) self.fetchGoals() } - @objc private func pickSortTapped() { - let alert = UIAlertController(title: "Gallery Sort Method", message: nil, preferredStyle: .actionSheet) - Constants.goalSortOptions.forEach { sortOption in - let isSelectedAlready = - UserDefaults.standard.value(forKey: Constants.selectedGoalSortKey) as? String == sortOption - let title = isSelectedAlready ? "--> " + sortOption : "" + sortOption - let action = UIAlertAction(title: title, style: .default) { [weak self] _ in - UserDefaults.standard.set(sortOption, forKey: Constants.selectedGoalSortKey) - UserDefaults.standard.synchronize() - Task { + private func sortMenu() -> UIMenu { + let deferred = UIDeferredMenuElement.uncached { [weak self] completion in + guard let self else { + completion([]) + return + } + let currentSort = + UserDefaults.standard.string(forKey: Constants.selectedGoalSortKey) ?? Constants.urgencyGoalSortString + let actions = Constants.goalSortOptions.map { sortOption in + UIAction( + title: sortOption, + state: sortOption == currentSort ? .on : .off + ) { [weak self] _ in + UserDefaults.standard.set(sortOption, forKey: Constants.selectedGoalSortKey) self?.fetchedResultsController.fetchRequest.sortDescriptors = Self.preferredSort try? self?.fetchedResultsController.performFetch() } } - alert.addAction(action) + completion(actions) } - alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) - self.present(alert, animated: true, completion: nil) + return UIMenu(title: "Sort by", options: .singleSelection, children: [deferred]) } } From ebda7036e4b515fe8d53bfdd5911d9ed5ee565b1 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sat, 25 Apr 2026 21:27:12 -0700 Subject: [PATCH 2/2] Apply swift-format to GalleryViewController Co-Authored-By: Claude Opus 4.6 (1M context) --- BeeSwift/Gallery/GalleryViewController.swift | 45 +++++++++----------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index ba478e50..c76406a6 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -47,7 +47,7 @@ class GalleryViewController: UIViewController { collectionView.register( UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, - withReuseIdentifier: "footer" + withReuseIdentifier: "footer", ) return collectionView }() @@ -107,7 +107,7 @@ class GalleryViewController: UIViewController { goalManager: GoalManager, healthStoreManager: HealthStoreManager, requestManager: RequestManager, - coordinator: MainCoordinator + coordinator: MainCoordinator, ) { self.currentUserManager = currentUserManager self.viewContext = viewContext @@ -122,7 +122,7 @@ class GalleryViewController: UIViewController { fetchRequest: fetchRequest, managedObjectContext: viewContext, sectionNameKeyPath: nil, - cacheName: nil + cacheName: nil, ) self.fetchRequest = fetchRequest super.init(nibName: nil, bundle: nil) @@ -135,13 +135,13 @@ class GalleryViewController: UIViewController { self, selector: #selector(self.userDefaultsDidChange), name: UserDefaults.didChangeNotification, - object: nil + object: nil, ) NotificationCenter.default.addObserver( self, selector: #selector(self.handleSignIn), name: CurrentUserManager.NotificationName.signedIn, - object: nil + object: nil, ) self.view.addSubview(self.stackView) stackView.snp.makeConstraints { (make) -> Void in make.edges.equalToSuperview() } @@ -149,13 +149,13 @@ class GalleryViewController: UIViewController { self, selector: #selector(self.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, - object: nil + object: nil, ) NotificationCenter.default.addObserver( self, selector: #selector(self.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, - object: nil + object: nil, ) configureDataSource() self.view.backgroundColor = .systemBackground @@ -168,12 +168,8 @@ class GalleryViewController: UIViewController { image: UIImage(systemName: "gearshape.fill"), style: UIBarButtonItem.Style.plain, target: self, - action: #selector(self.settingsButtonPressed) - ), - UIBarButtonItem( - image: UIImage(systemName: "arrow.up.arrow.down"), - menu: self.sortMenu() - ), + action: #selector(self.settingsButtonPressed), + ), UIBarButtonItem(image: UIImage(systemName: "arrow.up.arrow.down"), menu: self.sortMenu()), ] stackView.addArrangedSubview(self.freshnessIndicator) self.updateLastUpdatedLabel() @@ -295,7 +291,7 @@ class GalleryViewController: UIViewController { let alert = UIAlertController( title: "Error fetching goals", message: error.localizedDescription, - preferredStyle: .alert + preferredStyle: .alert, ) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) self.present(alert, animated: true, completion: nil) @@ -332,7 +328,7 @@ class GalleryViewController: UIViewController { let searchItem = UIBarButtonItem( barButtonSystemItem: .search, target: self, - action: #selector(self.searchButtonPressed) + action: #selector(self.searchButtonPressed), ) self.navigationItem.leftBarButtonItem = searchItem } @@ -378,7 +374,7 @@ class GalleryViewController: UIViewController { // After a rotation or other size change the optimal width for our cells may have changed. coordinator.animate( alongsideTransition: { _ in }, - completion: { _ in self.collectionViewLayout.invalidateLayout() } + completion: { _ in self.collectionViewLayout.invalidateLayout() }, ) } func openGoal(_ goal: Goal) { coordinator?.showGoal(goal) } @@ -400,7 +396,7 @@ class GalleryViewController: UIViewController { animations: { self.collectionView.contentInset.bottom = bottomInset self.collectionView.verticalScrollIndicatorInsets.bottom = bottomInset - } + }, ) } @@ -417,7 +413,7 @@ class GalleryViewController: UIViewController { animations: { self.collectionView.contentInset.bottom = 0 self.collectionView.verticalScrollIndicatorInsets.bottom = 0 - } + }, ) } private func configureDataSource() { @@ -430,7 +426,7 @@ class GalleryViewController: UIViewController { collectionView: collectionView, cellProvider: { collectionView, indexPath, goalObjectId in collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: goalObjectId) - } + }, ) dataSource.supplementaryViewProvider = { collectionView, kind, indexPath in collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "footer", for: indexPath) @@ -442,7 +438,7 @@ class GalleryViewController: UIViewController { extension GalleryViewController: NSFetchedResultsControllerDelegate { func controller( _ controller: NSFetchedResultsController, - didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference + didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference, ) { dataSource.apply(snapshot as GallerySnapshot, animatingDifferences: false) didUpdateGoals() @@ -463,10 +459,7 @@ extension GalleryViewController: SFSafariViewControllerDelegate { let currentSort = UserDefaults.standard.string(forKey: Constants.selectedGoalSortKey) ?? Constants.urgencyGoalSortString let actions = Constants.goalSortOptions.map { sortOption in - UIAction( - title: sortOption, - state: sortOption == currentSort ? .on : .off - ) { [weak self] _ in + UIAction(title: sortOption, state: sortOption == currentSort ? .on : .off) { [weak self] _ in UserDefaults.standard.set(sortOption, forKey: Constants.selectedGoalSortKey) self?.fetchedResultsController.fetchRequest.sortDescriptors = Self.preferredSort try? self?.fetchedResultsController.performFetch() @@ -491,7 +484,7 @@ extension GalleryViewController: UICollectionViewDelegateFlowLayout { func collectionView( _ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, - sizeForItemAt indexPath: IndexPath + sizeForItemAt indexPath: IndexPath, ) -> CGSize { let minimumWidth: CGFloat = 320 let itemSpacing = self.collectionViewLayout.minimumInteritemSpacing @@ -512,7 +505,7 @@ extension GalleryViewController: UICollectionViewDelegateFlowLayout { func collectionView( _ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, - referenceSizeForFooterInSection section: Int + referenceSizeForFooterInSection section: Int, ) -> CGSize { return CGSize(width: 320, height: section == 0 && self.filteredGoals.count > 0 ? 5 : 0) } }