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

add Custom View #93

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
82 changes: 78 additions & 4 deletions Sources/AlertToast/AlertToast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fileprivate struct AnimatedXmark: View {
//MARK: - Main View

@available(iOS 13, macOS 11, *)
public struct AlertToast: View{
public struct AlertToast<CustomView:View>: View{

public enum BannerAnimation{
case slide, pop
Expand All @@ -106,6 +106,9 @@ public struct AlertToast: View{

///Banner from the bottom of the view
case banner(_ transition: BannerAnimation)

/// custom View
case custom
}

/// Determine what the alert will display
Expand Down Expand Up @@ -199,6 +202,9 @@ public struct AlertToast: View{
///Customize your alert appearance
public var style: AlertStyle? = nil

///custom View
public var customView : (() -> CustomView)?

///Full init
public init(displayMode: DisplayMode = .alert,
type: AlertType,
Expand All @@ -223,6 +229,13 @@ public struct AlertToast: View{
self.title = title
}

///Short init with Custome View
public init(@ViewBuilder customView: @escaping () -> CustomView,style: AlertStyle? = nil){
self.type = .regular //default, no any meain
self.displayMode = .custom
self.customView = customView
self.style = style
}
///Banner from the bottom of the view
public var banner: some View{
VStack{
Expand Down Expand Up @@ -385,6 +398,19 @@ public struct AlertToast: View{
.alertBackground(style?.backgroundColor ?? nil)
.cornerRadius(10)
}
public var custom: some View{
ZStack{
if customView != nil {
customView!()
}else{
EmptyView()
}
}
.padding()
.alertBackground(style?.backgroundColor ?? nil)
.cornerRadius(10)
}


///Body init determine by `displayMode`
public var body: some View{
Expand All @@ -395,12 +421,14 @@ public struct AlertToast: View{
hud
case .banner:
banner
case .custom:
custom
}
}
}

@available(iOS 13, macOS 11, *)
public struct AlertToastModifier: ViewModifier{
public struct AlertToastModifier<CustomView:View>: ViewModifier{

///Presentation `Binding<Bool>`
@Binding var isPresenting: Bool
Expand All @@ -414,7 +442,7 @@ public struct AlertToastModifier: ViewModifier{
var offsetY: CGFloat = 0

///Init `AlertToast` View
var alert: () -> AlertToast
var alert: () -> AlertToast<CustomView>

///Completion block returns `true` after dismiss
var onTap: (() -> ())? = nil
Expand Down Expand Up @@ -504,6 +532,22 @@ public struct AlertToastModifier: ViewModifier{
completion?()
})
.transition(alert().displayMode == .banner(.slide) ? AnyTransition.slide.combined(with: .opacity) : AnyTransition.move(edge: .bottom))
case .custom:
alert()
.onTapGesture {
onTap?()
if tapToDismiss{
withAnimation(Animation.spring()){
self.workItem?.cancel()
isPresenting = false
self.workItem = nil
}
}
}
.onDisappear(perform: {
completion?()
})
.transition(AnyTransition.scale(scale: 0.8).combined(with: .opacity))
}

}
Expand All @@ -523,6 +567,8 @@ public struct AlertToastModifier: ViewModifier{
.valueChanged(value: isPresenting, onChange: { (presented) in
if presented{
onAppearAction()
}else{
onDisAppearAction()
}
})
case .hud:
Expand Down Expand Up @@ -550,6 +596,8 @@ public struct AlertToastModifier: ViewModifier{
.valueChanged(value: isPresenting, onChange: { (presented) in
if presented{
onAppearAction()
}else{
onDisAppearAction()
}
})
case .alert:
Expand All @@ -564,6 +612,24 @@ public struct AlertToastModifier: ViewModifier{
.valueChanged(value: isPresenting, onChange: { (presented) in
if presented{
onAppearAction()
}else{
onDisAppearAction()
}
})
case .custom:
content
.overlay(ZStack{
main()
.offset(y: offsetY)
}
.frame(maxWidth: screen.width, maxHeight: screen.height, alignment: .center)
.edgesIgnoringSafeArea(.all)
.animation(Animation.spring(), value: isPresenting))
.valueChanged(value: isPresenting, onChange: { (presented) in
if presented{
onAppearAction()
}else{
onDisAppearAction()
}
})
}
Expand Down Expand Up @@ -593,6 +659,14 @@ public struct AlertToastModifier: ViewModifier{
DispatchQueue.main.asyncAfter(deadline: .now() + duration, execute: task)
}
}
/// Cancel timer when interface leaves
private func onDisAppearAction(){
if workItem == nil {
return
}
workItem?.cancel()
workItem = nil
}
}

///Fileprivate View Modifier for dynamic frame when alert type is `.regular` / `.loading`
Expand Down Expand Up @@ -678,7 +752,7 @@ public extension View{
/// - show: Binding<Bool>
/// - alert: () -> AlertToast
/// - Returns: `AlertToast`
func toast(isPresenting: Binding<Bool>, duration: Double = 2, tapToDismiss: Bool = true, offsetY: CGFloat = 0, alert: @escaping () -> AlertToast, onTap: (() -> ())? = nil, completion: (() -> ())? = nil) -> some View{
func toast<T>(isPresenting: Binding<Bool>, duration: Double = 2, tapToDismiss: Bool = true, offsetY: CGFloat = 0, alert: @escaping () -> AlertToast<T>, onTap: (() -> ())? = nil, completion: (() -> ())? = nil) -> some View{
modifier(AlertToastModifier(isPresenting: isPresenting, duration: duration, tapToDismiss: tapToDismiss, offsetY: offsetY, alert: alert, onTap: onTap, completion: completion))
}

Expand Down