diff --git a/MijickPopups.podspec b/MijickPopups.podspec
index 82f2d4904..88d92b05c 100644
--- a/MijickPopups.podspec
+++ b/MijickPopups.podspec
@@ -5,7 +5,7 @@ Pod::Spec.new do |s|
MijickPopups solves two seemingly contradictory problems - to allow developers to create fully customizable popup, and to make the process as simple as possible.
DESC
- s.version = '4.0.0'
+ s.version = '4.0.1'
s.ios.deployment_target = '14.0'
s.osx.deployment_target = '12.0'
s.tvos.deployment_target = '15.0'
diff --git a/README.md b/README.md
index a3b26aaa0..e0b4785c0 100644
--- a/README.md
+++ b/README.md
@@ -63,26 +63,83 @@
-
+
-
+
-
+
-
+
-
+
+
+# ⨠Features
+
+
+ đą |
+ Three positions for the popups: Top, Center or Bottom |
+
+
+ đ |
+ Stackable popups |
+
+
+ đĢ |
+ Three height modes: Automatic, Large or Fullscreen |
+
+
+ âšī¸ |
+ Resizable popups |
+
+
+ đ |
+ Automatic dismissal |
+
+
+ đ |
+ Super easy to use from any place in the code |
+
+
+ đ§ |
+ Fully customizable |
+
+
+ đē |
+ Beautiful animations |
+
+
+ đ¤đŧ |
+ Gestures support |
+
+
+ đ |
+ Works with SwiftUI sheets |
+
+
+ đĨī¸ |
+ Supports iOS, macOS, tvOS, watchOS and visionOS |
+
+
+ âĄī¸ |
+ Supports Swift 6 |
+
+
+ đ |
+ ... and others |
+
+
+
# âī¸ Why MijickPopups?
MijickPopups library solves two seemingly contradictory problems - to allow developers to create fully customizable popup views, and to make the process as simple as possible. Here is why we think we have successfully met these objectives:
@@ -145,7 +202,7 @@ Join the welcoming community of developers on [Discord](https://link.mijick.com/
# đŧ Contribute
To contribute a feature or idea to **MijickPopups**, create an [issue](https://github.com/Mijick/Popups/issues/new?assignees=FulcrumOne&labels=state%3A+inactive%2C+type%3A+feature&projects=&template=đ-feature-request.md&title=%5BFREQ%5D) explaining your idea or bring it up on [Discord](https://discord.com/invite/dT5V7nm5SC).
If you find a bug, please create an [issue](https://github.com/Mijick/Popups/issues/new?assignees=FulcrumOne%2C+jay-jay-lama&labels=state%3A+inactive%2C+type%3A+bug&projects=&template=đĻ-bug-report.md&title=%5BBUG%5D).
-If you would like to contribute, please refer to the [Contribution Guidelines](https://link.mijick.com/contribution-guidelines).
+If you would like to contribute, please refer to the [Contribution Guidelines](https://github.com/Mijick/Popups/blob/main/.github/CONTRIBUTING.md).
# đ Sponsor our work
diff --git a/Sources/Internal/Containers/PopupStack.swift b/Sources/Internal/Containers/PopupStack.swift
index 382385665..7d87ecb3c 100644
--- a/Sources/Internal/Containers/PopupStack.swift
+++ b/Sources/Internal/Containers/PopupStack.swift
@@ -27,7 +27,6 @@ extension PopupStack {
}
-
// MARK: - STACK OPERATIONS
@@ -96,7 +95,6 @@ private extension PopupStack {
}
-
// MARK: - STACK CONTAINER OPERATIONS
diff --git a/Sources/Internal/Models/AnyPopup.swift b/Sources/Internal/Models/AnyPopup.swift
index e21246854..941754399 100644
--- a/Sources/Internal/Models/AnyPopup.swift
+++ b/Sources/Internal/Models/AnyPopup.swift
@@ -24,7 +24,6 @@ struct AnyPopup: Popup {
}
-
// MARK: - INITIALIZE & UPDATE
@@ -70,7 +69,6 @@ private extension AnyPopup {
}
-
// MARK: - PROTOCOLS CONFORMANCE
diff --git a/Sources/Internal/Models/ID+Popup.swift b/Sources/Internal/Models/ID+Popup.swift
index 866463dbf..99d4d7ee7 100644
--- a/Sources/Internal/Models/ID+Popup.swift
+++ b/Sources/Internal/Models/ID+Popup.swift
@@ -37,7 +37,6 @@ extension PopupID {
}
-
// MARK: - HELPERS
diff --git a/Sources/Internal/UI/PopupCenterStackView.swift b/Sources/Internal/UI/PopupCenterStackView.swift
index 0b6af71a2..e3d5526cb 100644
--- a/Sources/Internal/UI/PopupCenterStackView.swift
+++ b/Sources/Internal/UI/PopupCenterStackView.swift
@@ -15,12 +15,12 @@ struct PopupCenterStackView: View {
@ObservedObject var viewModel: VM.CenterStack
- var body: some View {
+ var body: some View { if viewModel.screen.height > 0 {
ZStack(content: createPopupStack)
.id(viewModel.popups.isEmpty)
.transition(transition)
.frame(maxWidth: .infinity, maxHeight: viewModel.screen.height)
- }
+ }}
}
private extension PopupCenterStackView {
func createPopupStack() -> some View {
diff --git a/Sources/Internal/UI/PopupVerticalStackView.swift b/Sources/Internal/UI/PopupVerticalStackView.swift
index cbeaa0685..67a0400e9 100644
--- a/Sources/Internal/UI/PopupVerticalStackView.swift
+++ b/Sources/Internal/UI/PopupVerticalStackView.swift
@@ -15,11 +15,11 @@ struct PopupVerticalStackView: View {
@ObservedObject var viewModel: VM.VerticalStack
- var body: some View {
+ var body: some View { if viewModel.screen.height > 0 {
ZStack(alignment: (!viewModel.alignment).toAlignment(), content: createPopupStack)
.frame(height: viewModel.screen.height, alignment: viewModel.alignment.toAlignment())
.onDragGesture(onChanged: viewModel.onPopupDragGestureChanged, onEnded: viewModel.onPopupDragGestureEnded, isEnabled: viewModel.dragGestureEnabled)
- }
+ }}
}
private extension PopupVerticalStackView {
func createPopupStack() -> some View {
diff --git a/Sources/Internal/UI/PopupView.swift b/Sources/Internal/UI/PopupView.swift
index b59e99cff..c80dd5294 100644
--- a/Sources/Internal/UI/PopupView.swift
+++ b/Sources/Internal/UI/PopupView.swift
@@ -22,6 +22,14 @@ struct PopupView: View {
private let bottomStackViewModel: VM.VerticalStack = .init(BottomPopupConfig.self)
+ init(rootView: any View, popupStack: PopupStack) {
+ #if os(tvOS)
+ self.rootView = rootView
+ #endif
+ self.stack = popupStack
+
+ Task { [self] in await updateViewModels { await $0.updatePopups(stack.popups) } }
+ }
var body: some View {
#if os(tvOS)
AnyView(rootView)
diff --git a/Sources/Internal/View Models/ViewModel+CentreStack.swift b/Sources/Internal/View Models/ViewModel+CentreStack.swift
index db6847549..257388fb1 100644
--- a/Sources/Internal/View Models/ViewModel+CentreStack.swift
+++ b/Sources/Internal/View Models/ViewModel+CentreStack.swift
@@ -16,12 +16,11 @@ extension VM { class CenterStack: ViewModel { required init() {}
var popups: [AnyPopup] = []
var activePopupProperties: ActivePopupProperties = .init()
var screen: Screen = .init()
- var updatePopupAction: ((AnyPopup) async -> ())!
- var closePopupAction: ((AnyPopup) async -> ())!
+ var updatePopupAction: ((AnyPopup) async -> ())?
+ var closePopupAction: ((AnyPopup) async -> ())?
}}
-
// MARK: - METHODS / VIEW MODEL / ACTIVE POPUP
@@ -84,7 +83,6 @@ extension VM.CenterStack {
}
-
// MARK: - METHODS / VIEW MODEL / SELECTED POPUP
@@ -104,7 +102,6 @@ private extension VM.CenterStack {
}
-
// MARK: - METHODS / VIEW
diff --git a/Sources/Internal/View Models/ViewModel+VerticalStack.swift b/Sources/Internal/View Models/ViewModel+VerticalStack.swift
index a29ca2e87..97f98cacc 100644
--- a/Sources/Internal/View Models/ViewModel+VerticalStack.swift
+++ b/Sources/Internal/View Models/ViewModel+VerticalStack.swift
@@ -16,12 +16,11 @@ extension VM { class VerticalStack: ViewModel { required init() {}
var popups: [AnyPopup] = []
var activePopupProperties: ActivePopupProperties = .init()
var screen: Screen = .init()
- var updatePopupAction: ((AnyPopup) async -> ())!
- var closePopupAction: ((AnyPopup) async -> ())!
+ var updatePopupAction: ((AnyPopup) async -> ())?
+ var closePopupAction: ((AnyPopup) async -> ())?
}}
-
// MARK: - METHODS / VIEW MODEL / ACTIVE POPUP
@@ -171,7 +170,6 @@ extension VM.VerticalStack {
}
-
// MARK: - METHODS / VIEW MODEL / SELECTED POPUP
@@ -214,7 +212,6 @@ private extension VM.VerticalStack {
}
-
// MARK: - METHODS / VIEW
@@ -307,7 +304,6 @@ extension VM.VerticalStack {
}
-
// MARK: - GESTURES
@@ -371,7 +367,7 @@ extension VM.VerticalStack {
}
private extension VM.VerticalStack {
func dismissLastPopupIfNeeded(_ popup: AnyPopup) async { switch activePopupProperties.translationProgress >= dragThreshold {
- case true: await closePopupAction(popup)
+ case true: await closePopupAction?(popup)
case false: return
}}
func calculateTargetDragHeight(_ activePopup: AnyPopup) async -> CGFloat {
diff --git a/Sources/Internal/View Models/ViewModel.swift b/Sources/Internal/View Models/ViewModel.swift
index 4f852add0..9340bdb03 100644
--- a/Sources/Internal/View Models/ViewModel.swift
+++ b/Sources/Internal/View Models/ViewModel.swift
@@ -21,8 +21,8 @@ enum VM {}
var screen: Screen { get set }
// MARK: Actions
- var updatePopupAction: ((AnyPopup) async -> ())! { get set }
- var closePopupAction: ((AnyPopup) async -> ())! { get set }
+ var updatePopupAction: ((AnyPopup) async -> ())? { get set }
+ var closePopupAction: ((AnyPopup) async -> ())? { get set }
// MARK: Methods
func calculateActivePopupHeight() async -> CGFloat?
@@ -35,7 +35,6 @@ enum VM {}
}
-
// MARK: - INITIALIZE & SETUP
@@ -54,7 +53,6 @@ extension ViewModel {
}
-
// MARK: UPDATE
@@ -95,7 +93,7 @@ extension ViewModel {
let newHeight = await calculatePopupHeight(heightCandidate, popup)
if newHeight != popup.height {
- await updatePopupAction(popup.updatedHeight(newHeight))
+ await updatePopupAction?(popup.updatedHeight(newHeight))
}
}
}
@@ -103,7 +101,7 @@ extension ViewModel {
// MARK: Popup Drag Height
extension ViewModel {
func updatePopupDragHeight(_ targetDragHeight: CGFloat, _ popup: AnyPopup) async {
- await updatePopupAction(popup.updatedDragHeight(targetDragHeight))
+ await updatePopupAction?(popup.updatedDragHeight(targetDragHeight))
}
}
diff --git a/Sources/Public/Setup/Public+Setup+SceneDelegate.swift b/Sources/Public/Setup/Public+Setup+SceneDelegate.swift
index 3e391b15f..e7adacfe9 100644
--- a/Sources/Public/Setup/Public+Setup+SceneDelegate.swift
+++ b/Sources/Public/Setup/Public+Setup+SceneDelegate.swift
@@ -73,7 +73,6 @@ extension PopupSceneDelegate {
}
-
// MARK: - WINDOW
diff --git a/Sources/Public/Setup/Public+Setup+View.swift b/Sources/Public/Setup/Public+Setup+View.swift
index 676d277a4..239e53c19 100644
--- a/Sources/Public/Setup/Public+Setup+View.swift
+++ b/Sources/Public/Setup/Public+Setup+View.swift
@@ -44,11 +44,11 @@ public extension View {
*/
func registerPopups(id: PopupStackID = .shared, configBuilder: @escaping (GlobalConfigContainer) -> GlobalConfigContainer = { $0 }) -> some View {
#if os(tvOS)
- PopupView(rootView: self, stack: .registerStack(id: id)).onAppear { _ = configBuilder(.init()) }
+ PopupView(rootView: self, popupStack: .registerStack(id: id)).onAppear { _ = configBuilder(.init()) }
#else
self
.frame(maxWidth: .infinity, maxHeight: .infinity)
- .overlay(PopupView(stack: .registerStack(id: id)), alignment: .top)
+ .overlay(PopupView(rootView: self, popupStack: .registerStack(id: id)), alignment: .top)
.onAppear { _ = configBuilder(.init()) }
#endif
}
diff --git a/Tests/Tests+PopupID.swift b/Tests/Tests+PopupID.swift
index c30460e79..a972982f1 100644
--- a/Tests/Tests+PopupID.swift
+++ b/Tests/Tests+PopupID.swift
@@ -16,7 +16,6 @@ import SwiftUI
@MainActor final class PopupIDTests: XCTestCase {}
-
// MARK: - TEST CASES
@@ -119,7 +118,6 @@ extension PopupIDTests {
}
-
// MARK: - HELPERS
diff --git a/Tests/Tests+PopupStack.swift b/Tests/Tests+PopupStack.swift
index 148bae864..59cbb272b 100644
--- a/Tests/Tests+PopupStack.swift
+++ b/Tests/Tests+PopupStack.swift
@@ -20,7 +20,6 @@ import SwiftUI
}
-
// MARK: - TEST CASES
@@ -241,7 +240,6 @@ extension PopupStackTests {
}
-
// MARK: - HELPERS
diff --git a/Tests/Tests+ViewModel+PopupCenterStack.swift b/Tests/Tests+ViewModel+PopupCenterStack.swift
index 47887c6aa..715d29109 100644
--- a/Tests/Tests+ViewModel+PopupCenterStack.swift
+++ b/Tests/Tests+ViewModel+PopupCenterStack.swift
@@ -37,7 +37,6 @@ private extension PopupCenterStackViewModelTests {
}
-
// MARK: - TEST CASES
@@ -223,7 +222,6 @@ private extension PopupCenterStackViewModelTests {
}
-
// MARK: - HELPERS
diff --git a/Tests/Tests+ViewModel+PopupVerticalStack.swift b/Tests/Tests+ViewModel+PopupVerticalStack.swift
index 2ca6c8267..b995cccc3 100644
--- a/Tests/Tests+ViewModel+PopupVerticalStack.swift
+++ b/Tests/Tests+ViewModel+PopupVerticalStack.swift
@@ -44,7 +44,6 @@ private extension PopupVerticalStackViewModelTests {
}
-
// MARK: - TEST CASES
@@ -133,7 +132,7 @@ extension PopupVerticalStackViewModelTests {
private extension PopupVerticalStackViewModelTests {
func appendPopupsAndCheckPopups(viewModel: ViewModel, popups: [AnyPopup], updatedPopup: AnyPopup, expectedValue: (height: CGFloat?, dragHeight: CGFloat)) async {
await viewModel.updatePopups(popups)
- await viewModel.updatePopupAction(updatedPopup)
+ await viewModel.updatePopupAction?(updatedPopup)
if let index = viewModel.popups.firstIndex(of: updatedPopup) {
XCTAssertEqual(viewModel.popups[index].height, expectedValue.height)
@@ -1475,7 +1474,6 @@ private extension PopupVerticalStackViewModelTests {
}
-
// MARK: - HELPERS