Skip to content

Commit

Permalink
Merge pull request #112 from patANZx/fix/vexillographer-nested-flags
Browse files Browse the repository at this point in the history
  • Loading branch information
bok- authored Jul 20, 2023
2 parents 6b8a039 + 3990c06 commit 9d6165d
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 109 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ios-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
- name: Build and Test
run: swift package generate-xcodeproj && xcrun xcodebuild test -scheme "Vexil-Package" -destination "platform=iOS Simulator,name=iPhone 8"
run: |
DEVICE_ID=`xcrun simctl list --json devices available iPhone | jq -r '.devices | to_entries | map(select(.value | add)) | sort_by(.key) | last.value | first.udid'`
swift package generate-xcodeproj
xcrun xcodebuild test -scheme "Vexil-Package" -destination "platform=iOS Simulator,id=$DEVICE_ID"
build-ios-macos-12:
runs-on: ubuntu-latest
Expand Down
6 changes: 5 additions & 1 deletion Sources/Vexil/Sources/UserDefaults+FlagValueSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ extension UserDefaults: FlagValueSource {
return
}

set(value.boxedFlagValue.object, forKey: key)
if value.boxedFlagValue.object == NSNull() {
set(Data(), forKey: key)
} else {
set(value.boxedFlagValue.object, forKey: key)
}

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ struct CaseIterableFlagControl<Value>: View where Value: FlagValue, Value: CaseI
@Binding
var showDetail: Bool

@Binding
var showPicker: Bool

// MARK: - View Body

var content: some View {
Expand All @@ -52,7 +49,7 @@ struct CaseIterableFlagControl<Value>: View where Value: FlagValue, Value: CaseI
var body: some View {
HStack {
if self.isEditable {
NavigationLink(destination: self.selector, isActive: self.$showPicker) {
NavigationLink(destination: self.selector) {
self.content
}
} else {
Expand All @@ -63,7 +60,7 @@ struct CaseIterableFlagControl<Value>: View where Value: FlagValue, Value: CaseI
}

var selector: some View {
return self.selectorList
SelectorList(value: self.$value)
.navigationBarTitle(Text(self.label), displayMode: .inline)
}

Expand Down Expand Up @@ -104,60 +101,66 @@ struct CaseIterableFlagControl<Value>: View where Value: FlagValue, Value: CaseI

#endif

var selectorList: some View {
Form {
ForEach(Value.allCases, id: \.self) { value in
Button(
action: {
self.value = value
self.showPicker = false
},
label: {
HStack {
FlagDisplayValueView(value: value)
.foregroundColor(.primary)
Spacer()

if value == self.value {
self.checkmark
struct SelectorList: View {
@Binding
var value: Value

@Environment(\.presentationMode)
private var presentationMode

var body: some View {
Form {
ForEach(Value.allCases, id: \.self) { value in
Button(
action: {
self.value = value
self.presentationMode.wrappedValue.dismiss()
},
label: {
HStack {
FlagDisplayValueView(value: value)
.foregroundColor(.primary)
Spacer()

if value == self.value {
self.checkmark
}
}
}
}
)
)
}
}
}
}

#if os(macOS)

var checkmark: some View {
return Text("")
}
var checkmark: some View {
return Text("")
}

#else

var checkmark: some View {
return Image(systemName: "checkmark")
}
var checkmark: some View {
return Image(systemName: "checkmark")
}

#endif

}
}


// MARK: - Creating CaseIterableFlagControls

@available(OSX 11.0, iOS 13.0, watchOS 7.0, tvOS 13.0, *)
protocol CaseIterableEditableFlag {
func control<RootGroup>(label: String, manager: FlagValueManager<RootGroup>, showDetail: Binding<Bool>, showPicker: Binding<Bool>) -> AnyView where RootGroup: FlagContainer
func control<RootGroup>(label: String, manager: FlagValueManager<RootGroup>, showDetail: Binding<Bool>) -> AnyView where RootGroup: FlagContainer
}

@available(OSX 11.0, iOS 13.0, watchOS 7.0, tvOS 13.0, *)
extension UnfurledFlag: CaseIterableEditableFlag
where Value: FlagValue, Value: CaseIterable, Value.AllCases: RandomAccessCollection,
Value: RawRepresentable, Value.RawValue: FlagValue, Value: Hashable
{
func control<RootGroup>(label: String, manager: FlagValueManager<RootGroup>, showDetail: Binding<Bool>, showPicker: Binding<Bool>) -> AnyView where RootGroup: FlagContainer {
func control<RootGroup>(label: String, manager: FlagValueManager<RootGroup>, showDetail: Binding<Bool>) -> AnyView where RootGroup: FlagContainer {
return CaseIterableFlagControl<Value>(
label: label,
value: Binding(
Expand All @@ -168,8 +171,7 @@ extension UnfurledFlag: CaseIterableEditableFlag
),
hasChanges: manager.hasValueInSource(flag: flag),
isEditable: manager.isEditable,
showDetail: showDetail,
showPicker: showPicker
showDetail: showDetail
)
.eraseToAnyView()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ struct OptionalCaseIterableFlagControl<Value>: View
@Binding
var showDetail: Bool

@Binding
var showPicker: Bool

// MARK: - View Body

var content: some View {
Expand All @@ -53,7 +50,7 @@ struct OptionalCaseIterableFlagControl<Value>: View
var body: some View {
HStack {
if self.isEditable {
NavigationLink(destination: self.selector, isActive: self.$showPicker) {
NavigationLink(destination: self.selector) {
self.content
}
} else {
Expand All @@ -66,82 +63,92 @@ struct OptionalCaseIterableFlagControl<Value>: View
#if os(iOS)

var selector: some View {
return self.selectorList
SelectorList(value: self.$value)
.navigationBarTitle(Text(self.label), displayMode: .inline)
}

#else

var selector: some View {
return self.selectorList
SelectorList(value: self.$value)
}

#endif

var selectorList: some View {
Form {
Section {
Button(
action: {
self.valueSelected(nil)
},
label: {
Text("None")
.foregroundColor(.primary)
Spacer()

if self.value.wrapped == nil {
self.checkmark
struct SelectorList: View {
@Binding
var value: Value

@Environment(\.presentationMode)
private var presentationMode

var body: some View {
Form {
Section {
Button(
action: {
self.valueSelected(nil)
},
label: {
HStack {
Text("None")
.foregroundColor(.primary)
Spacer()

if self.value.wrapped == nil {
self.checkmark
}
}
}
}
)
}
)
}

ForEach(Value.WrappedFlagValue.allCases, id: \.self) { value in
Button(
action: {
self.valueSelected(value)
},
label: {
FlagDisplayValueView(value: value)
Spacer()

if value == self.value.wrapped {
self.checkmark
ForEach(Value.WrappedFlagValue.allCases, id: \.self) { value in
Button(
action: {
self.valueSelected(value)
},
label: {
HStack {
FlagDisplayValueView(value: value)
.foregroundColor(.primary)
Spacer()

if value == self.value.wrapped {
self.checkmark
}
}
}
}
)
)
}
}
}
}

#if os(macOS)

var checkmark: some View {
return Text("")
}
var checkmark: some View {
return Text("")
}

#else

var checkmark: some View {
return Image(systemName: "checkmark")
}
var checkmark: some View {
return Image(systemName: "checkmark")
}

#endif

func valueSelected(_ value: Value.WrappedFlagValue?) {
self.value.wrapped = value
showPicker = false
func valueSelected(_ value: Value.WrappedFlagValue?) {
self.value.wrapped = value
presentationMode.wrappedValue.dismiss()
}
}

}


// MARK: - Creating CaseIterableFlagControls

@available(OSX 11.0, iOS 13.0, watchOS 7.0, tvOS 13.0, *)
protocol OptionalCaseIterableEditableFlag {
func control<RootGroup>(label: String, manager: FlagValueManager<RootGroup>, showDetail: Binding<Bool>, showPicker: Binding<Bool>) -> AnyView where RootGroup: FlagContainer
func control<RootGroup>(label: String, manager: FlagValueManager<RootGroup>, showDetail: Binding<Bool>) -> AnyView where RootGroup: FlagContainer
}

@available(OSX 11.0, iOS 13.0, watchOS 7.0, tvOS 13.0, *)
Expand All @@ -150,7 +157,7 @@ extension UnfurledFlag: OptionalCaseIterableEditableFlag
Value.WrappedFlagValue.AllCases: RandomAccessCollection, Value.WrappedFlagValue: RawRepresentable,
Value.WrappedFlagValue.RawValue: FlagValue, Value.WrappedFlagValue: Hashable
{
func control<RootGroup>(label: String, manager: FlagValueManager<RootGroup>, showDetail: Binding<Bool>, showPicker: Binding<Bool>) -> AnyView where RootGroup: FlagContainer {
func control<RootGroup>(label: String, manager: FlagValueManager<RootGroup>, showDetail: Binding<Bool>) -> AnyView where RootGroup: FlagContainer {
let key = info.key

return OptionalCaseIterableFlagControl<Value>(
Expand All @@ -159,7 +166,7 @@ extension UnfurledFlag: OptionalCaseIterableEditableFlag
get: { Value(manager.flagValue(key: key)) },
set: { newValue in
do {
try manager.setFlagValue(newValue.wrapped, key: key)
try manager.setFlagValue(newValue, key: key)

} catch {
print("[Vexilographer] Could not set flag with key \"\(key)\" to \"\(newValue)\"")
Expand All @@ -168,8 +175,7 @@ extension UnfurledFlag: OptionalCaseIterableEditableFlag
),
hasChanges: manager.hasValueInSource(flag: flag),
isEditable: manager.isEditable,
showDetail: showDetail,
showPicker: showPicker
showDetail: showDetail
)
.eraseToAnyView()
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/Vexillographer/FlagGroupView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct UnfurledFlagGroupView<Group, Root>: View where Group: FlagContainer, Root
Section {
// Filter out all links. They won't work on the mac flag group view.
ForEach(self.group.allItems().filter { $0.isLink == false }, id: \.id) { item in
item.unfurledView
UnfurledFlagItemView(item: item)
}
}
}
Expand Down Expand Up @@ -98,7 +98,7 @@ struct UnfurledFlagGroupView<Group, Root>: View where Group: FlagContainer, Root

var flags: some View {
ForEach(self.group.allItems(), id: \.id) { item in
item.unfurledView
UnfurledFlagItemView(item: item)
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Vexillographer/FlagSectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct UnfurledFlagSectionView<Group, Root>: View where Group: FlagContainer, Ro

private var content: some View {
ForEach(self.group.allItems(), id: \.id) { item in
item.unfurledView
UnfurledFlagItemView(item: item)
}
}

Expand Down
8 changes: 2 additions & 6 deletions Sources/Vexillographer/FlagView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ struct UnfurledFlagView<Value, RootGroup>: View where Value: FlagValue, RootGrou
@State
private var showDetail = false

@State
private var showPicker = false


// MARK: - Initialisation

init(flag: UnfurledFlag<Value, RootGroup>, manager: FlagValueManager<RootGroup>) {
Expand Down Expand Up @@ -65,10 +61,10 @@ struct UnfurledFlagView<Value, RootGroup>: View where Value: FlagValue, RootGrou
return flag.control(label: self.flag.info.name, manager: self.manager, showDetail: self.$showDetail)

} else if let flag = self.flag as? CaseIterableEditableFlag {
return flag.control(label: self.flag.info.name, manager: self.manager, showDetail: self.$showDetail, showPicker: self.$showPicker)
return flag.control(label: self.flag.info.name, manager: self.manager, showDetail: self.$showDetail)

} else if let flag = self.flag as? OptionalCaseIterableEditableFlag {
return flag.control(label: self.flag.info.name, manager: self.manager, showDetail: self.$showDetail, showPicker: self.$showPicker)
return flag.control(label: self.flag.info.name, manager: self.manager, showDetail: self.$showDetail)

} else if let flag = self.flag as? StringEditableFlag {
return flag.control(label: self.flag.info.name, manager: self.manager, showDetail: self.$showDetail)
Expand Down
Loading

0 comments on commit 9d6165d

Please sign in to comment.