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

[trello.com/c/sI4VXuJa] Added swipe gestures (left & down) to Snackbar #595

Merged
merged 5 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ struct NotificationModel: Equatable, Hashable {
let title: String?
let description: String?
let tapHandler: IDWrapper<() -> Void>?
let cancelAutoDismiss: IDWrapper<() -> Void>?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// NotificationPresenterView.swift
// PopupKit
//
// Created by Yana Silosieva on 02.12.2024.
//

import SwiftUI
import CommonKit

struct NotificationPresenterView: View {
enum DragDirection {
case vertical
case horizontal
}

@State private var verticalDragTranslation: CGFloat = .zero
@State private var horizontalDragTranslation: CGFloat = .zero
@State private var minTranslationYForDismiss: CGFloat = .infinity
@State private var minTranslationXForDismiss: CGFloat = .infinity
@State private var isTextLimited: Bool = true
@State private var dismissEdge: Edge = .top
@State private var dragDirection: DragDirection?

let model: NotificationModel
let safeAreaInsets: EdgeInsets
let dismissAction: () -> Void

var body: some View {
NotificationView(
isTextLimited: $isTextLimited,
model: model
)
.padding([.leading, .trailing], 15)
.padding([.top, .bottom], 10)
.background(GeometryReader(content: processGeometry))
.expanded(axes: .horizontal)
.offset(y: verticalDragTranslation < .zero ? verticalDragTranslation : .zero)
.offset(x: horizontalDragTranslation < .zero ? horizontalDragTranslation : .zero)
.gesture(dragGesture)
.onTapGesture(perform: onTap)
.cornerRadius(10)
.padding(.horizontal, 15)
.padding(.top, safeAreaInsets.top)
.transition(.move(edge: dismissEdge))
}
}

private extension NotificationPresenterView {
var dragGesture: some Gesture {
DragGesture()
.onChanged {
if dragDirection == nil {
dragDirection = abs($0.translation.height) > abs($0.translation.width) ? .vertical : .horizontal
}
switch dragDirection {
case .vertical:
verticalDragTranslation = $0.translation.height
case .horizontal:
horizontalDragTranslation = $0.translation.width
case .none:
break
}
}
.onEnded {
if $0.velocity.height < -100 || -$0.translation.height > minTranslationYForDismiss {
dismissEdge = .top
Task { dismissAction() }
} else if $0.velocity.width < -100 || $0.translation.width > minTranslationXForDismiss {
dismissEdge = .leading
Task { dismissAction() }
} else if $0.velocity.height > -100 || -$0.translation.height < minTranslationYForDismiss {
withAnimation {
horizontalDragTranslation = .zero
isTextLimited = false
}
model.cancelAutoDismiss?.value()
} else {
withAnimation {
verticalDragTranslation = .zero
horizontalDragTranslation = .zero
}
}
dragDirection = nil
}
}

func processGeometry(_ geometry: GeometryProxy) -> some View {
DispatchQueue.main.async {
minTranslationYForDismiss = geometry.size.height / 2
minTranslationXForDismiss = geometry.size.width / 2
}

return Color.init(uiColor: .adamant.swipeBlockColor)
.cornerRadius(10)
}

func onTap() {
model.tapHandler?.value()
dismissAction()
dismissEdge = .top
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ import SwiftUI
import CommonKit

struct NotificationView: View {
@State private var dragTranslation: CGFloat = .zero
@State private var minTranslationForDismiss: CGFloat = .infinity

@Binding var isTextLimited: Bool
let model: NotificationModel
let safeAreaInsets: EdgeInsets
let dismissAction: () -> Void

var body: some View {
HStack(alignment: .top, spacing: 8) {
Expand All @@ -24,15 +20,6 @@ struct NotificationView: View {
textStack
Spacer(minLength: .zero)
}
.padding([.leading, .trailing], 15)
.padding([.top, .bottom], 10)
.background(GeometryReader(content: processGeometry))
.gesture(dragGesture)
.onTapGesture(perform: onTap)
.background(Color(.adamant.swipeBlockColor))
.cornerRadius(10)
.padding(.horizontal, 15)
.padding(.top, safeAreaInsets.top)
}
}

Expand All @@ -48,42 +35,17 @@ private extension NotificationView {
}

var textStack: some View {
VStack(alignment: .leading, spacing: .zero) {
VStack(alignment: .leading, spacing: 3) {
if let title = model.title {
Text(title)
.font(.system(size: 15, weight: .bold))
}
if let description = model.description {
Text(description)
.font(.system(size: 13))
.lineLimit(3)
}
}
}

var dragGesture: some Gesture {
DragGesture()
.onChanged { dragTranslation = $0.translation.height }
.onEnded {
print(-$0.translation.height, minTranslationForDismiss)
if $0.velocity.height < -100 || -$0.translation.height > minTranslationForDismiss {
dismissAction()
} else {
withAnimation { dragTranslation = .zero }
}
.lineLimit(isTextLimited ? 3 : nil)

}
}

func processGeometry(_ geometry: GeometryProxy) -> some View {
DispatchQueue.main.async {
minTranslationForDismiss = geometry.size.height / 2
}

return Color.clear
}

func onTap() {
model.tapHandler?.value()
dismissAction()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@ private extension PopupCoordinatorView {
func makeNotificationView(safeAreaInsets: EdgeInsets) -> some View {
VStack {
if let notificationModel = model.notification {
NotificationView(
NotificationPresenterView(
model: notificationModel,
safeAreaInsets: safeAreaInsets,
dismissAction: { [weak model] in
model?.notification = nil
}
)
.id(model.notification?.hashValue)
.transition(.move(edge: .top))
}
Spacer()
}
Expand Down
5 changes: 4 additions & 1 deletion PopupKit/Sources/PopupKit/PopupManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ public extension PopupManager {
icon: icon,
title: title,
description: description,
tapHandler: tapHandler.map { .init(id: .empty, value: $0) }
tapHandler: tapHandler.map { .init(id: .empty, value: $0) },
cancelAutoDismiss: .init(id: .empty, value: { [weak self] in
self?.autoDismissManager.notificationDismissSubscription?.cancel()
})
)

if autoDismiss {
Expand Down