Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 🐛 [JIRA: IOSSDKBUG-157] isActive needed for ListPickerItem #690

Merged
merged 1 commit into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct ListPickerItemExample: View {
case identifiable
case objectItem
case stringItem
case activeChildren
case searchable
case searchableListView
var id: Self { self }
Expand Down Expand Up @@ -85,6 +86,12 @@ struct ListPickerItemExample: View {
{
Text("StringItem")
}
case .activeChildren:
NavigationLink(
destination: ListPickerItemActiveChildrenExample())
{
Text("Active Children Directly")
}
case .searchable:
NavigationLink(
destination: ListPickerItemWithSearchExample())
Expand Down Expand Up @@ -299,8 +306,48 @@ public struct ListPickerItemWithStringExample: View {
}
}

struct ListPickerItemActiveChildrenExample: View {
private let model = ListPickerItemDataModel.data

@State var selections: Set<String> = []
@State var isActive: Bool = true

public init() {}

public var body: some View {
List {
ListPickerItem(key: {
Text("Frameworks")
}, value: {
let str = Array(selections).joined(separator: ", ")
Text(str)
}, configuration:
ListPickerItemConfiguration(self.model, id: \.name, children: \.children, selection: self.$selections, isActive: self.$isActive, rowContent: { framework in
Text(framework.name)
}))
}
.listPickerListViewModifier { c in
c.navigationBarTitle(Text("Children"))
}
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button {
self.isActive.toggle()
} label: {
Image(systemName: "switch.2")
}
}
}
.navigationBarTitle(Text("Parent"))
}
}

struct ListPickerItemPreview: PreviewProvider {
static var previews: some View {
NavigationStack {
ListPickerItemActiveChildrenExample()
}

NavigationView {
ListPickerItemDataNonIdentifiableExample()
}
Expand Down
62 changes: 46 additions & 16 deletions Sources/FioriSwiftUICore/Views/ListPickerItem+View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,20 @@ extension Fiori {

extension ListPickerItem: View {
public var body: some View {
NavigationLink(
destination: self.destinationView,
label: {
KeyValueItem {
key
} value: {
value
if let isActive = destinationConfiguration?.isActive, isActive.wrappedValue {
self.destinationView
} else {
NavigationLink(
destination: self.destinationView,
label: {
KeyValueItem {
key
} value: {
value
}
}
}
)
)
}
}

@ViewBuilder
Expand Down Expand Up @@ -73,6 +77,9 @@ public extension ListPickerItem {
public struct ListPickerItemConfiguration {
let destinationView: AnyView

// A boolean that indicates whether show the children directly.
var isActive: Binding<Bool>?

/// Creates a searchable configuration object from a collection of data which supports single-level picker with the ability to select.
/// - Parameters:
/// - data: The data for constructing the list picker.
Expand Down Expand Up @@ -118,16 +125,18 @@ public struct ListPickerItemConfiguration {
/// - id: The key path to the data model's unique identifier.
/// - children: The key path to the optional property of a data element whose value indicates the children of that element.
/// - selection: A binding to a set which stores the selected items.
/// - isActive: A binding to a bool that decide if show children directly, Default value is nil.
/// - rowContent: The view builder which returns the content of each row in the list picker.
public init<Data, ID, RowContent>(_ data: Data,
id: KeyPath<Data.Element, ID>,
children: KeyPath<Data.Element, Data?>?,
selection: Binding<Set<ID>>?,
isActive: Binding<Bool>? = nil,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Data: RandomAccessCollection, RowContent: View, ID: Hashable
{
self.destinationView = List {
ForEach(data, id: id) { element in
if let isActive, isActive.wrappedValue {
self.destinationView = ForEach(data, id: id) { element in
let row = rowContent(element)
let id_value = element[keyPath: id]

Expand All @@ -140,24 +149,44 @@ public struct ListPickerItemConfiguration {
} else {
ListPickerItem.Row(content: row, id: id_value, selection: selection)
}
}
}.typeErased
}.typeErased
} else {
self.destinationView = List {
ForEach(data, id: id) { element in
let row = rowContent(element)
let id_value = element[keyPath: id]

if let children, let childrenData = element[keyPath: children] {
ListPickerItem<RowContent, EmptyView>(key: {
row
}, value: {
EmptyView()
}, configuration: ListPickerItemConfiguration(childrenData, id: id, children: children, selection: selection, rowContent: rowContent))
} else {
ListPickerItem.Row(content: row, id: id_value, selection: selection)
}
}
}.typeErased
}
self.isActive = isActive
}

/// Creates a configuration object from a collection of data (conforms to `Identifiable`) which supports both single-level and multi-level picker with the ability to select multiple items.
/// - Parameters:
/// - data: The data for constructing the list picker.
/// - children: The key path to the optional property of a data element whose value indicates the children of that element.
/// - selection: A binding to a set which stores the selected items.
/// - isActive: A binding to a bool that decide if show children directly, Default value is nil.
/// - rowContent: The view builder which returns the content of each row in the list picker.
public init<Data, ID>(_ data: Data,
children: KeyPath<Data.Element, Data?>?,
selection: Binding<Set<ID>>?,
isActive: Binding<Bool>? = nil,
@ViewBuilder rowContent: @escaping (Data.Element) -> some View)
where Data: RandomAccessCollection, Data.Element: Identifiable, ID == Data.Element.ID
{
let id = \Data.Element.id
self.init(data, id: id, children: children, selection: selection, rowContent: rowContent)
self.init(data, id: id, children: children, selection: selection, isActive: isActive, rowContent: rowContent)
}
}

Expand All @@ -166,8 +195,9 @@ public extension ListPickerItemConfiguration {
/// - Parameters:
/// - data: An array of strings for constructing the list.
/// - selection: A binding to a set which stores the selected items.
init(_ data: [String], selection: Binding<Set<String>>?) {
self.init(data, id: \.self, children: nil, selection: selection) { str in
/// - isActive: A binding to a bool that decide if show children directly, Default value is nil.
init(_ data: [String], selection: Binding<Set<String>>?, isActive: Binding<Bool>? = nil) {
self.init(data, id: \.self, children: nil, selection: selection, isActive: isActive) { str in
Text(str)
}
}
Expand Down
Loading