Skip to content

Commit

Permalink
Adding togglePresence to array variants of StoredValue and AsyncStore…
Browse files Browse the repository at this point in the history
…dValue
  • Loading branch information
mergesort committed Dec 13, 2023
1 parent 5582089 commit c9044d7
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 6 deletions.
41 changes: 35 additions & 6 deletions Sources/Boutique/StoredValue+Array.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public extension StoredValue {
public extension StoredValue where Item: RangeReplaceableCollection {
/// A function to append a @``StoredValue`` represented by an `Array`
/// without having to manually make an intermediate copy for every value update.
///
Expand All @@ -14,9 +14,16 @@ public extension StoredValue {
/// try await self.$redPandaList.append("Pabu")
/// ```
@MainActor
func append<Value>(_ value: Value) where Item == [Value] {
func append(_ item: Item.Element) {
var updatedArray = self.wrappedValue
updatedArray.append(value)
updatedArray.append(item)
self.set(updatedArray)
}

@MainActor
func togglePresence<Value: Equatable>(_ value: Value) where Item == [Value] {
var updatedArray = self.wrappedValue
updatedArray.togglePresence(value)
self.set(updatedArray)
}
}
Expand Down Expand Up @@ -48,7 +55,7 @@ public extension SecurelyStoredValue {
}
}

public extension AsyncStoredValue {
public extension AsyncStoredValue where Item: RangeReplaceableCollection {
/// A function to append a @``StoredValue`` represented by an `Array`
/// without having to manually make an intermediate copy for every value update.
///
Expand All @@ -63,9 +70,31 @@ public extension AsyncStoredValue {
/// ```
/// try await self.$redPandaList.append("Pabu")
/// ```
func append<Value>(_ value: Value) async throws where Item == [Value] {
func append(_ item: Item.Element) async throws {
var updatedArray = self.wrappedValue
updatedArray.append(value)
updatedArray.append(item)
try await self.set(updatedArray)
}

@MainActor
func togglePresence<Value: Equatable>(_ value: Value) async throws where Item == [Value] {
var updatedArray = self.wrappedValue
updatedArray.togglePresence(value)
try await self.set(updatedArray)
}
}

private extension Array where Element: Equatable {
/// Adds a tag to an array if the tag doesn't exist in the array, otherwise removes the tag from the array.
/// This is useful for actions like a user tapping a button, where the current existence
/// of the tag in the array may not be known.
///
/// - Parameter tag: The tag to add or remove
mutating func togglePresence(_ item: Element) {
if self.contains(where: { $0 == item }) {
self.removeAll(where: { $0 == item })
} else {
self.append(item)
}
}
}
17 changes: 17 additions & 0 deletions Tests/BoutiqueTests/AsyncStoredValueTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,23 @@ final class AsyncStoredValueTests: XCTestCase {
XCTAssertEqual(self.storedArrayValue, [BoutiqueItem.sweater, BoutiqueItem.belt])
}

func testStoredArrayValueTogglePresence() async throws {
XCTAssertEqual(self.storedArrayValue, [])

try await self.$storedArrayValue.togglePresence(.sweater)
XCTAssertEqual(self.storedArrayValue, [.sweater])

try await self.$storedArrayValue.togglePresence(.sweater)
XCTAssertEqual(self.storedArrayValue, [])

try await self.$storedArrayValue.togglePresence(.sweater)
try await self.$storedArrayValue.togglePresence(.belt)
XCTAssertEqual(self.storedArrayValue, [.sweater, .belt])

try await self.$storedArrayValue.togglePresence(.belt)
XCTAssertEqual(self.storedArrayValue, [.sweater])
}

func testStoredBinding() async throws {
XCTAssertEqual(self.$storedBinding.binding.wrappedValue, Binding.constant(BoutiqueItem.sweater).wrappedValue)

Expand Down
17 changes: 17 additions & 0 deletions Tests/BoutiqueTests/StoredValueTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,23 @@ final class StoredValueTests: XCTestCase {
XCTAssertEqual(self.storedArrayValue, [BoutiqueItem.sweater, BoutiqueItem.belt])
}

func testStoredArrayValueTogglePresence() async throws {
XCTAssertEqual(self.storedArrayValue, [])

await self.$storedArrayValue.togglePresence(.sweater)
XCTAssertEqual(self.storedArrayValue, [.sweater])

await self.$storedArrayValue.togglePresence(.sweater)
XCTAssertEqual(self.storedArrayValue, [])

await self.$storedArrayValue.togglePresence(.sweater)
await self.$storedArrayValue.togglePresence(.belt)
XCTAssertEqual(self.storedArrayValue, [.sweater, .belt])

await self.$storedArrayValue.togglePresence(.belt)
XCTAssertEqual(self.storedArrayValue, [.sweater])
}

@MainActor
func testStoredBinding() async throws {
// Using wrappedValue for our tests to work around the fact that Binding doesn't conform to Equatable
Expand Down

0 comments on commit c9044d7

Please sign in to comment.