Skip to content

Commit

Permalink
Make contexts inject themselves as environment object
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsaidi committed Apr 22, 2024
1 parent fa6fbf6 commit 5c4f154
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 35 deletions.
11 changes: 11 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ SwiftUIKit makes its best effort to honor semver, but breaking changes can occur



## 4.2.1

### 💡 Behavior changes

* `View.alert` now injects the context as environment object.
* `View.label` now takes a localized string key instead of a key.
* `View.sheet` now injects the context as environment object.
* `View.fullScreenCover` now injects the context as environment object.



## 4.2

This version refactors many views to take their styles & configs as environment values, instead of injecting them in the initializer.
Expand Down
20 changes: 19 additions & 1 deletion Sources/SwiftUIKit/Extensions/View+Label.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,31 @@ public extension View {
///
/// - Parameters:
/// - text: The label text.
func label(_ text: String) -> some View {
func label(
_ text: LocalizedStringKey,
bundle: Bundle? = nil
) -> some View {
Label {
Text(text)
} icon: {
self
}
}

/// Convert the view to a localized label.
///
/// - Parameters:
/// - text: The label text.
func localizedLabel(
_ text: LocalizedStringKey,
bundle: Bundle? = nil
) -> some View {
Label {
Text(text, bundle: bundle)
} icon: {
self
}
}
}

#Preview {
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftUIKit/Gestures/GestureButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import SwiftUI

/**
This button supports triggering different gestures in a way
that maximized performance.
that maximizes performance.

This button can't be used in a `ScrollView` since it blocks
the scroll view gesture. To implement multi-gesture support
Expand Down
13 changes: 4 additions & 9 deletions Sources/SwiftUIKit/Gestures/ScrollViewGestureButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,12 @@ import SwiftUI
This button supports triggering different gestures in a way
that works within a `ScrollView`.

This button can't be used in a `ScrollView` since it blocks
the scroll view gesture. To implement multi-gesture support
in a `ScrollView`, use a ``ScrollViewGestureButton``.

This button can be used in a `ScrollView` and doesn't block
the scroll view gesture despite applying many gestures. The
complicated code is the result of much trial and error, and
has been tested to not affect the scrolling or any gestures.
This button does npt block scroll view gesture. The code is
the result of much trial & error and has been tested to not
affect scrolling.

If you don't need to use a scroll view, you should consider
using a ``GestureButton`` instead.
using a ``GestureButton`` instead.-

Note that the view uses an underlying `ButtonStyle` to make
gestures work. It can thus not apply another style, but you
Expand Down
26 changes: 10 additions & 16 deletions Sources/SwiftUIKit/Lists/ListButtonStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@

import SwiftUI

/**
This style makes buttons take up the entire row and applies
a content shape that makes the entire view tappable.

You can apply the style with `.buttonStyle(.list)`, and can
apply it to an entire list, just as with other styles.
*/
/// This style makes the button take up the entire row, then
/// applies a shape that makes the entire view tappable.
///
/// You can apply this style with `.buttonStyle(.list)`, and
/// can apply it to an entire list, like any other style.
public struct ListButtonStyle: ButtonStyle {

/// Create a custom style.
Expand Down Expand Up @@ -61,9 +59,11 @@ public extension ButtonStyle where Self == ListButtonStyle {

var body: some View {
List {
ForEach(0...100, id: \.self) {
button("Button \($0)")
.buttonStyle($0 == 0 ? .list : .list(pressedOpacity: 0.1))
ForEach(0...100, id: \.self) { index in
Button("Button \(index)") {
overlayText = "\(index) tapped!"
}
.buttonStyle(index == 0 ? .list : .list(pressedOpacity: 0.1))
}
}
.overlay(overlay)
Expand All @@ -78,12 +78,6 @@ public extension ButtonStyle where Self == ListButtonStyle {
.opacity(overlayText.isEmpty ? 0 : 1)
.onTapGesture { overlayText = "" }
}

func button(_ name: String) -> some View {
Button(name) {
overlayText = "\(name) tapped!"
}
}
}

return Preview()
Expand Down
9 changes: 6 additions & 3 deletions Sources/SwiftUIKit/Presentation/AlertContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ import SwiftUI

In the code above, we create a custom, static `Alert` value
to easily let us share and reuse alerts in an app or domain.
You can also use enums to define multiple alerts.

You can also setup a global context in the application root,
and pass it as an environment object, to get a single value.
This view modifier will also inject the provided context as
an environment object into the view hierarchy, to let other
views in the same view hierarchy reuse the same context.
*/
public class AlertContext: PresentationContext<Alert> {

Expand All @@ -52,10 +52,13 @@ public class AlertContext: PresentationContext<Alert> {
public extension View {

/// Bind an ``AlertContext`` to the view.
///
/// This also injects this context as environment object.
func alert(_ context: AlertContext) -> some View {
alert(
isPresented: context.isActiveBinding,
content: context.content ?? { Alert(title: Text("")) }
)
.environmentObject(context)
}
}
12 changes: 9 additions & 3 deletions Sources/SwiftUIKit/Presentation/FullScreenCoverContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ import SwiftUI
}
```

You can also setup a global context in the application root,
and pass it as an environment object, to get a single value.
This view modifier will also inject the provided context as
an environment object into the view hierarchy, to let other
views in the same view hierarchy reuse the same context.
*/
public class FullScreenCoverContext: PresentationContext<AnyView> {

Expand All @@ -46,11 +47,16 @@ import SwiftUI
public extension View {

/// Bind an ``FullScreenCoverContext`` to the view.
func fullScreenCover(_ context: FullScreenCoverContext) -> some View {
///
/// This also injects this context as environment object.
func fullScreenCover(
_ context: FullScreenCoverContext
) -> some View {
fullScreenCover(
isPresented: context.isActiveBinding,
content: context.content ?? EmptyView().any
)
.environmentObject(context)
}
}
#endif
8 changes: 6 additions & 2 deletions Sources/SwiftUIKit/Presentation/SheetContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ import SwiftUI
}
```

You can also setup a global context in the application root,
and pass it as an environment object, to get a single value.
This view modifier will also inject the provided context as
an environment object into the view hierarchy, to let other
views in the same view hierarchy reuse the same context.
*/
public class SheetContext: PresentationContext<AnyView> {

Expand All @@ -41,10 +42,13 @@ public class SheetContext: PresentationContext<AnyView> {
public extension View {

/// Bind an ``SheetContext`` to the view.
///
/// This also injects this context as environment object.
func sheet(_ context: SheetContext) -> some View {
sheet(
isPresented: context.isActiveBinding,
content: context.content ?? EmptyView().any
)
.environmentObject(context)
}
}

0 comments on commit 5c4f154

Please sign in to comment.