Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
banghuazhao committed Aug 30, 2024
1 parent fc739db commit 83bc05a
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 2 deletions.
Binary file added Images/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import PackageDescription

let package = Package(
name: "EasyToast",
platforms: [
.iOS(.v15)
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
Expand Down
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# EasyToast

**EasyToast** is a simple, lightweight, flexible, and easy-to-use library for showing toast in **SwiftUI**. Whether you need a quick and easy way to present a brief message to your users or a fully custom-designed toast, EasyToast provides the tools to do it seamlessly.

## Features

- **Simple Text Toasts**: Display a quick message to the user with just a few lines of code.
- **Custom Toast Views**: Create and display fully custom-designed toast notifications.
- **Flexible Positioning**: Position the toast at the top, center, or bottom of the screen.
- **Configurable Duration**: Control how long the toast remains visible.

## 🧳 Requirements

- iOS 15.0+
- Swift 5+

## 💻 Installation

### Swift Package Manager

You can add EasyToast to your project using [Swift Package Manager](https://swift.org/package-manager/).

1. In Xcode, go to `File > Add Packages...`
2. Enter the package URL: https://github.com/banghuazhao/EasyToast
3. Select the desired version or branch and add it to your project.

## 🛠 Usage

### Displaying a Simple Toast

To display a simple toast with a message, use the `easyToast` modifier:

```swift
import EasyToast

var body: some View {
content
.easyToast(isPresented: $showToast, message: "This is a toast message")
}
```

<img src="./Images/1.png" width=200 />

### Displaying a Simple Toast on Top

To display a simple toast with a message, use the `easyToast` modifier:

```swift
var body: some View {
content
.easyToast(isPresented: $showToast, message: "This is a toast message on top", position: .top)
}
```

<img src="./Images/2.png" width=200 />

### Displaying a Custom Toast

To display a custom-designed toast view, use the `easyToast` modifier with a custom view:

```swift
var body: some View {
content
.easyToast(isPresented: $showToast, duration: 3, position: .bottom) {
HStack {
Image(systemName: "checkmark.circle")
.foregroundColor(.white)
Text("Show Custom Toast Success")
.foregroundColor(.white)
}
.padding()
.background(Color.green)
.cornerRadius(20)
}
}
```

<img src="./Images/3.png" width=200 />

## 💡 Idea

The toast is implemented by overlaying a custom view on top of the view that applies the `.easyToast` modifier, ensuring it seamlessly appears over the current content without disrupting the underlying layout
184 changes: 182 additions & 2 deletions Sources/EasyToast/EasyToast.swift
Original file line number Diff line number Diff line change
@@ -1,2 +1,182 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book
//
// Created by Banghua Zhao on 30/08/2024
// Copyright Apps Bay Limited. All rights reserved.
//

import SwiftUI

public enum ToastPosition {
case top
case center
case bottom
}

struct EasyToast<CustomView: View>: ViewModifier {
@Binding var isPresented: Bool
private let message: String?
private let duration: Double
private let position: ToastPosition
let customView: CustomView?

init(
isPresented: Binding<Bool>,
message: String? = nil,
position: ToastPosition,
duration: Double,
customView: CustomView? = nil
) {
_isPresented = isPresented
self.message = message
self.duration = duration
self.position = position
self.customView = customView
}

@State private var showToast: Bool = false

public func body(content: Content) -> some View {
content
.overlay(alignment: alignment) {
if showToast {
toast
}
}
.onChange(of: isPresented) { newValue in
if newValue == true {
withAnimation {
showToast = true
}
Task { @MainActor in
try? await Task.sleep(nanoseconds: UInt64(duration) * 1000000000)
withAnimation {
isPresented = false
showToast = false
}
}
}
}
}

@ViewBuilder
private var toast: some View {
switch position {
case .top:
toastView
.transition(.move(edge: .top).combined(with: .opacity))
case .center:
toastView
.transition(.opacity)
case .bottom:
toastView
.transition(.move(edge: .bottom).combined(with: .opacity))
}
}

@ViewBuilder
private var toastView: some View {
if let customView {
customView
} else if let message {
SimpleMessageView(message: message)
} else {
EmptyView()
}
}

private var alignment: Alignment {
switch position {
case .top:
.top
case .center:
.center
case .bottom:
.bottom
}
}
}

public extension View {
/**
Displays a simple toast notification with a text message.

- Parameters:
- isPresented: A binding to a boolean value that determines whether the toast is presented.
- message: The message text to be displayed in the toast.
- duration: The duration in seconds for which the toast is displayed. The default value is 2 seconds.
- position: The position on the screen where the toast is displayed. The default is `.center`.

- Returns: A view that displays the original content overlaid with a toast notification when `isPresented` is `true`.

Use this method to present a brief message to the user. The toast will automatically disappear after the specified duration.

- Note: The toast will only appear when `isPresented` is set to `true`.

Example usage:
```swift
Text("Hello, World!")
.easyToast(isPresented: $showToast, message: "This is a toast message")
```
*/
func easyToast(
isPresented: Binding<Bool>,
message: String,
duration: Double = 2,
position: ToastPosition = .center
) -> some View {
modifier(
EasyToast<EmptyView>(
isPresented: isPresented,
message: message,
position: position,
duration: duration
)
)
}

/**
Displays a toast notification with a custom view.

- Parameters:
- isPresented: A binding to a boolean value that determines whether the toast is presented.
- duration: The duration in seconds for which the toast is displayed. The default value is 2 seconds.
- position: The position on the screen where the toast is displayed. The default is `.center`.
- customView: A closure that returns the custom view to be displayed as the toast content.

- Returns: A view that displays the original content overlaid with a custom toast view when `isPresented` is `true`.

Use this method to present a custom-designed toast view. The toast will automatically disappear after the specified duration.

- Note: The toast will only appear when `isPresented` is set to `true`.

Example usage:
```swift
Text("Hello, World!")
.easyToast(isPresented: $showToast, duration: 3, position: .bottom) {
HStack {
Image(systemName: "checkmark.circle")
.foregroundColor(.white)
Text("Show Custom Toast Success")
.foregroundColor(.white)
}
.padding()
.background(Color.green)
.cornerRadius(20)
}
```
*/
func easyToast(
isPresented: Binding<Bool>,
duration: Double = 2,
position: ToastPosition = .center,
@ViewBuilder customView: @escaping () -> some View
) -> some View {
modifier(
EasyToast(
isPresented: isPresented,
position: position,
duration: duration,
customView: customView()
)
)
}
}
19 changes: 19 additions & 0 deletions Sources/EasyToast/SimpleMessageView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Created by Banghua Zhao on 30/08/2024
// Copyright Apps Bay Limited. All rights reserved.
//

import SwiftUI

struct SimpleMessageView: View {
let message: String

var body: some View {
Text(message)
.padding()
.background(Color.black.opacity(0.7))
.foregroundColor(.white)
.cornerRadius(20)
.shadow(radius: 10)
}
}

0 comments on commit 83bc05a

Please sign in to comment.