Skip to content

Commit

Permalink
IOS-9146: BottomSheet actions (#299)
Browse files Browse the repository at this point in the history
* feat(BottomSheet): Rename Action into ActionList

* feat(BottomSheet): Add button actions

* feat(BottomSheet): Update styling

* feat(BottomSheet): Update tests

* feat(BottomSheet): Added more actions on catalog

* IOS-9146: Merge cases for informative types

* IOS-9146: Update tests

* IOS-9146: Add more catalog options

* Run swiftformat

BREAKING CHANGE: Action type has been renamed as ActionList. To use the previous actions(items: [ActionItem]) rename the case in your project as actionList(items: [ActionListItem]). Also ActionItem has been renamed as ActionListItem.

---------

Co-authored-by: WanaldinoTelefonica <WanaldinoTelefonica@users.noreply.github.com>
  • Loading branch information
WanaldinoTelefonica and WanaldinoTelefonica authored Aug 31, 2023
1 parent 977b1d9 commit e380ecc
Show file tree
Hide file tree
Showing 178 changed files with 222 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ private enum Section: Int, CaseIterable {
case informativeIconType
case imageType
case actionStyle
case actions
case showSheet
}

Expand Down Expand Up @@ -87,7 +88,8 @@ class UICatalogSheetViewController: UIViewController {

cell.segmentedControl.insertSegment(withTitle: "Single Selection", at: 0, animated: false)
cell.segmentedControl.insertSegment(withTitle: "Informative", at: 1, animated: false)
cell.segmentedControl.insertSegment(withTitle: "Action", at: 2, animated: false)
cell.segmentedControl.insertSegment(withTitle: "Action List", at: 2, animated: false)
cell.segmentedControl.insertSegment(withTitle: "Action", at: 3, animated: false)

cell.segmentedControl.selectedSegmentIndex = 0
return cell
Expand Down Expand Up @@ -125,6 +127,24 @@ class UICatalogSheetViewController: UIViewController {
return cell
}()

private lazy var primaryActionEnabledCell: UISwitchTableViewCell = {
let cell = UISwitchTableViewCell(reuseIdentifier: "primaryActionEnabled")
cell.textLabel?.text = "Primary Action"
return cell
}()

private lazy var secondaryActionEnabledCell: UISwitchTableViewCell = {
let cell = UISwitchTableViewCell(reuseIdentifier: "primaryActionEnabled")
cell.textLabel?.text = "Secondary Action"
return cell
}()

private lazy var linkActionEnabledCell: UISwitchTableViewCell = {
let cell = UISwitchTableViewCell(reuseIdentifier: "primaryActionEnabled")
cell.textLabel?.text = "Link Action"
return cell
}()

private lazy var showSheetCell: UITableViewCell = {
let cell = UITableViewCell(style: .default, reuseIdentifier: "showSheet")
cell.textLabel?.textColor = .textLink
Expand All @@ -143,6 +163,11 @@ class UICatalogSheetViewController: UIViewController {
[informativeIconTypeCell],
[iconURLTypeCell],
[actionStyleCell],
[
primaryActionEnabledCell,
secondaryActionEnabledCell,
linkActionEnabledCell
],
[showSheetCell]
]

Expand Down Expand Up @@ -210,6 +235,8 @@ extension UICatalogSheetViewController: UITableViewDataSource, UITableViewDelega
case 1:
configuration = informativeSheet
case 2:
configuration = actionListSheet
case 3:
configuration = actionSheet
default:
fatalError("Unhandled sheet type")
Expand Down Expand Up @@ -350,11 +377,11 @@ private extension UICatalogSheetViewController {
return configuration
}

var actionSheet: SheetConfiguration {
var rows: [ActionItem] = []
var actionListSheet: SheetConfiguration {
var rows: [ActionListItem] = []

for index in 1 ... sheetNumElements {
let item = ActionItem(
let item = ActionListItem(
id: index.description,
title: "List Item \(index)",
style: actionStyleCell.segmentedControl.selectedSegmentIndex == 0 ? .normal : .destructive,
Expand All @@ -366,7 +393,7 @@ private extension UICatalogSheetViewController {
}
let content = SheetList(
id: UUID().uuidString,
listType: .actions(items: rows),
listType: .actionList(items: rows),
autoSubmit: true,
selectedId: []
)
Expand All @@ -382,6 +409,48 @@ private extension UICatalogSheetViewController {

return configuration
}

var actionSheet: SheetConfiguration {
var actions = [ActionItem]()
if primaryActionEnabledCell.isOn {
actions.append(ActionItem(
id: UUID().uuidString,
style: .primary,
title: "Primary Button"
))
}
if secondaryActionEnabledCell.isOn {
actions.append(ActionItem(
id: UUID().uuidString,
style: .secondary,
title: "Secondary Button"
))
}
if linkActionEnabledCell.isOn {
actions.append(ActionItem(
id: UUID().uuidString,
style: .link,
title: "Link Button",
rightImage: .chevron
))
}

let configuration = SheetConfiguration(
header: SheetHeader(
title: sheetTitle,
subtitle: sheetSubtitle,
description: sheetDescription
),
content: [SheetList(
id: UUID().uuidString,
listType: .actions(items: actions),
autoSubmit: true,
selectedId: []
)]
)

return configuration
}
}

private extension Section {
Expand All @@ -397,6 +466,7 @@ private extension Section {
case .informativeIconType: return "Informative icon type"
case .imageType: return "Image format"
case .actionStyle: return "Action style"
case .actions: return "Actions"
case .showSheet: return nil
}
}
Expand Down
30 changes: 24 additions & 6 deletions Sources/Mistica/Components/Sheet/Model/SheetConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,15 @@ public struct SheetList {

public enum SheetListType {
case singleSelection(items: [SingleSelectionItem])
case actions(items: [ActionItem])
case actionList(items: [ActionListItem])
case informative(items: [InformativeItem])
case actions(items: [ActionItem])

var isInformative: Bool {
switch self {
case .informative:
return true
case .singleSelection:
return false
case .actions:
case .singleSelection, .actionList, .actions:
return false
}
}
Expand Down Expand Up @@ -159,7 +158,7 @@ public enum InformativeItemIcon: Equatable {
}
}

public struct ActionItem {
public struct ActionListItem {
public enum Style {
case normal
case destructive
Expand All @@ -174,7 +173,7 @@ public struct ActionItem {
public init(
id: String,
title: String,
style: ActionItem.Style,
style: ActionListItem.Style,
url: String?,
urlDark: String?
) {
Expand All @@ -185,3 +184,22 @@ public struct ActionItem {
self.urlDark = urlDark
}
}

public struct ActionItem {
let id: String
let style: Button.Style
let title: String
let rightImage: Button.RightImage?

public init(
id: String,
style: Button.Style,
title: String,
rightImage: Button.RightImage? = nil
) {
self.id = id
self.style = style
self.title = title
self.rightImage = rightImage
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ListFragmentView: UIView {
enum ItemTappedType {
case singleSelection(item: SingleSelectionItem)
case informative(item: InformativeItem)
case actionList(item: ActionListItem)
case action(item: ActionItem)
}

Expand Down Expand Up @@ -61,10 +62,12 @@ private extension ListFragmentView {
switch sheetList.listType {
case .singleSelection(let items):
fillListWithSingleSelectionItems(items)
case .actions(let items):
case .actionList(let items):
fillListWithActionItems(items)
case .informative(let items):
fillListWithInformativeItems(items)
case .actions(items: let items):
fillList(with: items)
}

backgroundColor = .backgroundContainer
Expand Down Expand Up @@ -99,7 +102,7 @@ private extension ListFragmentView {
}
}

func fillListWithActionItems(_ items: [ActionItem]) {
func fillListWithActionItems(_ items: [ActionListItem]) {
for item in items {
let rowView = ActionRow(item: item)

Expand All @@ -114,6 +117,29 @@ private extension ListFragmentView {
}
}

func fillList(with items: [ActionItem]) {
let buttons = items.enumerated().map(button(at:for:))

let stackView = UIStackView(arrangedSubviews: buttons)
stackView.axis = .vertical
stackView.spacing = 16
stackView.layoutMargins = UIEdgeInsets(top: 16, left: 0, bottom: 16, right: 0)
stackView.isLayoutMarginsRelativeArrangement = true

self.stackView.addArrangedSubview(stackView)
}

func button(at index: Int, for action: ActionItem) -> Button {
let button = Button(
style: action.style,
title: action.title,
rightImage: action.rightImage
)
button.tag = index
button.addTarget(self, action: #selector(didTap(action:)), for: .touchUpInside)
return button
}

@objc private func didTouchItem(_ sender: UILongPressGestureRecognizer) {
guard let touchable = sender.view as? Touchable else { return }

Expand Down Expand Up @@ -146,7 +172,7 @@ private extension ListFragmentView {
if let tappedView = sender.view as? SingleSelectionRowView {
handleSingleSelectionRowTap(tappedView)
} else if let tappedView = sender.view as? ActionRow {
handleActionsRowTap(tappedView)
handleActionListRowTap(tappedView)
}
@unknown default:
// ignores this states
Expand All @@ -164,8 +190,15 @@ private extension ListFragmentView {
delegate(.singleSelection(item: tappedView.item))
}

func handleActionsRowTap(_ tappedView: ActionRow) {
delegate(.action(item: tappedView.item))
func handleActionListRowTap(_ tappedView: ActionRow) {
delegate(.actionList(item: tappedView.item))
}

@objc
func didTap(action button: Button) {
guard case .actions(let items) = sheetList.listType else { return }
let item = items[button.tag]
delegate(.action(item: item))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import UIKit

class ActionRow: UIStackView {
let item: ActionItem
let item: ActionListItem

init(item: ActionItem) {
init(item: ActionListItem) {
self.item = item

super.init(frame: .zero)
Expand All @@ -26,7 +26,7 @@ class ActionRow: UIStackView {

private let titleLabel: IntrinsictHeightLabel = {
let label = IntrinsictHeightLabel()
label.minHeight = 64
label.minHeight = 72
label.numberOfLines = 0
label.textColor = .textPrimary
return label
Expand Down
12 changes: 7 additions & 5 deletions Sources/Mistica/Components/Sheet/View/SheetViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class SheetViewController: UIViewController {
label.numberOfLines = 0
label.textAlignment = .left
label.textColor = .textPrimary
label.font = .textPreset4(weight: .regular)
label.font = .textPreset5()
return label
}
return nil
Expand All @@ -55,7 +55,7 @@ public class SheetViewController: UIViewController {
label.text = subtitle
label.numberOfLines = 0
label.textColor = .textPrimary
label.font = .textPreset2(weight: .regular)
label.font = .textPreset3(weight: .regular)
return label
}
return nil
Expand Down Expand Up @@ -164,7 +164,7 @@ public extension SheetViewController {

handleView.translatesAutoresizingMaskIntoConstraints = false
handleView.heightAnchor.constraint(equalToConstant: 4.0).isActive = true
handleView.widthAnchor.constraint(equalToConstant: 24.0).isActive = true
handleView.widthAnchor.constraint(equalToConstant: 32.0).isActive = true
topStackView.addArrangedSubview(CenterView(arrangedSubview: handleView, axis: .horizontal))
containerView.addArrangedSubview(topStackView)

Expand All @@ -190,7 +190,7 @@ public extension SheetViewController {
headerStackView.translatesAutoresizingMaskIntoConstraints = false
contentStackView.addArrangedSubview(headerStackView)

contentStackView.stackView.setCustomSpacing(4, after: headerStackView)
contentStackView.stackView.setCustomSpacing(8, after: headerStackView)

if let subtitleLabel = subtitleLabel {
headerStackView.addArrangedSubview(subtitleLabel)
Expand Down Expand Up @@ -229,12 +229,14 @@ private extension SheetViewController {
func handleListRowTapped(_ sheetList: SheetList, rowTapped: ListFragmentView.ItemTappedType) {
if sheetList.autoSubmit {
switch rowTapped {
case .action(let item):
case .actionList(let item):
sheetSelectionResponse = .init(action: .submit, selectedIds: [.init(id: sheetList.id, selected: [item.id])])
case .informative:
sheetSelectionResponse = .init(action: .submit, selectedIds: [])
case .singleSelection(let item):
sheetSelectionResponse = .init(action: .submit, selectedIds: [.init(id: sheetList.id, selected: [item.id])])
case .action(item: let item):
sheetSelectionResponse = .init(action: .submit, selectedIds: [.init(id: sheetList.id, selected: [item.id])])
}

DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak self] in
Expand Down
Loading

0 comments on commit e380ecc

Please sign in to comment.