diff --git a/Tusker/Screens/Timeline/TimelineViewController.swift b/Tusker/Screens/Timeline/TimelineViewController.swift index 97090f88..8a9dd290 100644 --- a/Tusker/Screens/Timeline/TimelineViewController.swift +++ b/Tusker/Screens/Timeline/TimelineViewController.swift @@ -43,8 +43,12 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro override func loadView() { var config = UICollectionLayoutListConfiguration(appearance: .plain) - // TODO: swipe actions - // config.trailingSwipeActionsConfigurationProvider = + config.leadingSwipeActionsConfigurationProvider = { [unowned self] in + (collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions() + } + config.trailingSwipeActionsConfigurationProvider = { [unowned self] in + (collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.trailingSwipeActions() + } config.itemSeparatorHandler = { [unowned self] indexPath, sectionSeparatorConfiguration in guard let item = self.dataSource.itemIdentifier(for: indexPath) else { return sectionSeparatorConfiguration diff --git a/Tusker/Views/Status/TimelineStatusCollectionViewCell.swift b/Tusker/Views/Status/TimelineStatusCollectionViewCell.swift index 17078852..f5ca1dad 100644 --- a/Tusker/Views/Status/TimelineStatusCollectionViewCell.swift +++ b/Tusker/Views/Status/TimelineStatusCollectionViewCell.swift @@ -509,6 +509,61 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti toggleReblog() } + func leadingSwipeActions() -> UISwipeActionsConfiguration? { + guard mastodonController.loggedIn, + let status = mastodonController.persistentContainer.status(for: statusID) else { + return nil + } + + let favoriteTitle = status.favourited ? "Unfavorite" : "Favorite" + let favorite = UIContextualAction(style: .normal, title: favoriteTitle) { [unowned self] _, _, completion in + Task { + await FavoriteService(status: status, mastodonController: self.mastodonController, presenter: self.delegate!).toggleFavorite() + completion(true) + } + } + favorite.image = UIImage(systemName: "star.fill") + favorite.backgroundColor = status.favourited ? UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1) : UIColor(displayP3Red: 1, green: 204/255, blue: 0, alpha: 1) + + let reblogTitle = status.reblogged ? "Unreblog" : "Reblog" + let reblog = UIContextualAction(style: .normal, title: reblogTitle) { _, _, completion in + Task { + await ReblogService(status: status, mastodonController: self.mastodonController, presenter: self.delegate!).toggleReblog() + completion(true) + } + } + reblog.image = UIImage(systemName: "repeat") + reblog.backgroundColor = status.reblogged ? UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1) : tintColor + + return UISwipeActionsConfiguration(actions: [favorite, reblog]) + } + + func trailingSwipeActions() -> UISwipeActionsConfiguration? { + var actions = [UIContextualAction]() + + let share = UIContextualAction(style: .normal, title: "Share") { [unowned self] _, _, completion in + self.delegate?.showMoreOptions(forStatus: statusID, sourceView: self) + completion(true) + } + // bold to more closesly match other action symbols + let config = UIImage.SymbolConfiguration(weight: .bold) + share.image = UIImage(systemName: "square.and.arrow.up")!.applyingSymbolConfiguration(config)! + share.backgroundColor = .lightGray + actions.append(share) + + if mastodonController.loggedIn { + let reply = UIContextualAction(style: .normal, title: "Reply") { [unowned self] _, _, completion in + self.replyPressed() + completion(true) + } + reply.image = UIImage(systemName: "arrowshape.turn.up.left.fill") + reply.backgroundColor = tintColor + actions.insert(reply, at: 0) + } + + return UISwipeActionsConfiguration(actions: actions) + } + } extension TimelineStatusCollectionViewCell: UIContextMenuInteractionDelegate {