Compare commits

..

2 Commits

Author SHA1 Message Date
Saint b8764b5577 swiping a bit better 2024-06-24 00:53:15 -04:00
Saint 3af58e417f stable scrolling and drag 2024-06-23 19:36:21 -04:00
2 changed files with 169 additions and 111 deletions

View File

@ -101,8 +101,10 @@ class ShowTitle: NSObject, ObservableObject {
@Published var chapVisible = false @Published var chapVisible = false
} }
struct Pane: View { struct Pane: View {
@ObservedObject var paneConnector: PaneConnector @ObservedObject var paneConnector: PaneConnector
@ObservedObject var scrollDelegate: ScrollDelegate
@StateObject var showTitle = ShowTitle() @StateObject var showTitle = ShowTitle()
// @State var chapVisible = false // @State var chapVisible = false
@ -202,12 +204,11 @@ struct Pane: View {
let reactive = self.refresh let reactive = self.refresh
} }
// if self.paneConnector != nil { scrollView.canCancelContentTouches = false
// let reactive = self.paneConnector scrollView.delegate = scrollDelegate
// }
DispatchQueue.main.async { DispatchQueue.main.async {
if paneConnector.setScrollOffset != nil { if paneConnector.setScrollOffset != nil {
scrollView.contentOffset.y = scrollView.contentOffset.y + paneConnector.setScrollOffset! scrollView.contentOffset.y = scrollView.contentOffset.y + paneConnector.setScrollOffset!
paneConnector.setScrollOffset = nil paneConnector.setScrollOffset = nil

View File

@ -215,6 +215,7 @@ func makeVerseView(seg: SegDenorm) -> some View {
} }
class PaneConnector: NSObject, ObservableObject { class PaneConnector: NSObject, ObservableObject {
var showOverlay: Bool = false var showOverlay: Bool = false
@Published var refresh: Bool = false @Published var refresh: Bool = false
@Published var vertSep = CGFloat(20) @Published var vertSep = CGFloat(20)
@ -225,9 +226,27 @@ class PaneConnector: NSObject, ObservableObject {
@Published var scrollOffset = CGFloat() @Published var scrollOffset = CGFloat()
@Published var hasMoved = false @Published var hasMoved = false
var setScrollOffset: CGFloat? var setScrollOffset: CGFloat?
@Published var disableScroll = false
} }
class ScrollDelegate: NSObject, ObservableObject, UIScrollViewDelegate {
@Published var isScrolling = false
func scrollViewWillBeginDragging(_: UIScrollView) {
print("pop started scroll")
isScrolling.toggle()
}
func scrollViewDidEndDragging(_: UIScrollView, willDecelerate _: Bool) {
print("pop ended scroll")
isScrolling.toggle()
}
}
struct ContentView: View { struct ContentView: View {
// this is for the whole view swiping // this is for the whole view swiping
@State var mainSwipe = CGSize.zero @State var mainSwipe = CGSize.zero
@ -236,6 +255,7 @@ struct ContentView: View {
@State var selection = 0 @State var selection = 0
@StateObject var paneConnector = PaneConnector() @StateObject var paneConnector = PaneConnector()
@StateObject var scrollDelegate = ScrollDelegate()
@State var refresh: Bool = false @State var refresh: Bool = false
@ -248,6 +268,8 @@ struct ContentView: View {
@State var dragOffset = CGFloat(0) @State var dragOffset = CGFloat(0)
@GestureState var dragGestureActive = CGSize.zero
enum SwipeStartState { enum SwipeStartState {
case center case center
case right case right
@ -271,10 +293,13 @@ struct ContentView: View {
init() { init() {
UITableView.appearance().backgroundColor = UIColor(Color(red: 0.2, green: 0.2, blue: 0.2)) UITableView.appearance().backgroundColor = UIColor(Color(red: 0.2, green: 0.2, blue: 0.2))
_selectedRibbon = Query(SelectedRibbonRequest()) _selectedRibbon = Query(SelectedRibbonRequest())
} }
var body: some View { var body: some View {
var fontSize = CGFloat(15) var fontSize = CGFloat(15)
var scale = 0.65 var scale = 0.65
var height = CGFloat(50) var height = CGFloat(50)
@ -327,6 +352,7 @@ struct ContentView: View {
// Top pane // Top pane
Pane(paneConnector: paneConnector, Pane(paneConnector: paneConnector,
scrollDelegate: scrollDelegate,
selectedRibbon: selectedRibbon, selectedRibbon: selectedRibbon,
width: geometry.size.width - 15, width: geometry.size.width - 15,
height: geometry.size.height + 20, height: geometry.size.height + 20,
@ -340,7 +366,7 @@ struct ContentView: View {
// .onChanged { gesture in // .onChanged { gesture in
// paneConnector.vertSep = paneConnector.vertSep - gesture.translation.height // paneConnector.vertSep = paneConnector.vertSep - gesture.translation.height
// } // }
// ) //
// // Bottom pane // // Bottom pane
// ScrollViewReader { _ in // ScrollViewReader { _ in
@ -372,9 +398,14 @@ struct ContentView: View {
.offset(x: 20, y: 0) .offset(x: 20, y: 0)
.offset(x: pulledOut.width) .offset(x: pulledOut.width)
.offset(x: mainSwipe.width) .offset(x: mainSwipe.width)
.gesture( .highPriorityGesture(
DragGesture() DragGesture(minimumDistance: 20)
.updating($dragGestureActive) { value, state, _ in
print("pop here")
state = value.translation
}
.onChanged { value in .onChanged { value in
print("pop changed")
// Calculate the offset // Calculate the offset
let margin = CGFloat(30) let margin = CGFloat(30)
@ -392,50 +423,29 @@ struct ContentView: View {
print("start swipe meow: \(startSwipeState)") print("start swipe meow: \(startSwipeState)")
} }
if newOffset > 0 { if newOffset > 0 {
startSwipeDir = .right startSwipeDir = .right
} else { } else {
startSwipeDir = .left startSwipeDir = .left
}
// Apply resistance if out of bounds
var maxOffsetRight: CGFloat = 110
var maxOffsetLeft: CGFloat = 200
if startSwipeState == .right {
if startSwipeDir == .right {
maxOffsetRight = .zero
maxOffsetLeft = .zero
} else if startSwipeDir == .left {
maxOffsetRight = CGFloat(110)
maxOffsetLeft = CGFloat(-30)
}
} else if startSwipeState == .left {
if startSwipeDir == .left {
maxOffsetLeft = .zero
maxOffsetRight = .zero
} else if startSwipeDir == .right {
maxOffsetLeft = CGFloat(200)
maxOffsetRight = CGFloat(10)
}
} }
if newOffset + pulledOut.width < -maxOffsetLeft { // Apply resistance if out of bounds
if startSwipeState == .right && startSwipeDir == .left { let maxRight: CGFloat = 140
newOffset = -maxOffsetLeft + rubberBandEffect(newOffset + maxOffsetLeft) - pulledOut.width let finalRight: CGFloat = 110
} else { let rightDiff = maxRight - finalRight
newOffset = -maxOffsetLeft + rubberBandEffect(newOffset + maxOffsetLeft) var maxOffsetLeft: CGFloat = -200
}
} else if newOffset + pulledOut.width > maxOffsetRight { if newOffset > maxRight , pulledOut.width == 0 {
if startSwipeState == .left, startSwipeDir == .right { // newOffset = maxRight + rubberBandEffect(newOffset)
newOffset = maxOffsetRight + rubberBandEffect(newOffset - maxOffsetRight) - pulledOut.width newOffset = maxRight + rubberBandEffect(newOffset - maxRight)
} else { }
newOffset = maxOffsetRight + rubberBandEffect(newOffset - maxOffsetRight)
} if newOffset > rightDiff, pulledOut.width > 0 {
newOffset = rightDiff + rubberBandEffect(newOffset - rightDiff)
}
if newOffset < maxOffsetLeft, pulledOut.width == 0 {
newOffset = maxOffsetLeft + rubberBandEffect(newOffset)
} }
self.mainSwipe.width = newOffset self.mainSwipe.width = newOffset
@ -443,83 +453,130 @@ struct ContentView: View {
// dragOffset is what is used to make the text be readable // dragOffset is what is used to make the text be readable
// with the right pane being visible // with the right pane being visible
// if mainSwipe.width < -margin && pulledOut.width <= 0 { if mainSwipe.width < -margin, pulledOut.width <= 0 {
if mainSwipe.width < -margin && pulledOut.width <= 0 {
dragOffset = margin + mainSwipe.width + pulledOut.width dragOffset = margin + mainSwipe.width + pulledOut.width
} }
if mainSwipe.width > 0 && pulledOut.width < 0 { if mainSwipe.width > 0, pulledOut.width < 0 {
dragOffset = margin + mainSwipe.width + pulledOut.width dragOffset = margin + mainSwipe.width + pulledOut.width
} }
} }
.onEnded { _ in .onEnded { _ in
var finalSwipe = CGFloat(0) onDragEnded()
let swipeLeftFinal = CGFloat(-200)
let swipeRightFinal = CGFloat(110)
let margin = CGFloat(30)
var setDragOffset = CGFloat(0)
if startSwipeState == .center {
if startSwipeDir == .right {
finalSwipe = swipeRightFinal
} else {
finalSwipe = swipeLeftFinal
setDragOffset = margin + swipeLeftFinal
}
} else if startSwipeState == .right {
finalSwipe = .zero
if startSwipeDir == .left {
finalSwipe = .zero
} else {
finalSwipe = swipeRightFinal
}
} else if startSwipeState == .left {
if startSwipeDir == .left {
finalSwipe = swipeLeftFinal
setDragOffset = margin + swipeLeftFinal
} else {
finalSwipe = .zero
}
}
startSwipeState = nil
startSwipeDir = nil
print("foo")
// if mainSwipe.width < 0 && pulledOut.width > 0 {
// setPulledOutWith = CGFloat(0)
// } else if mainSwipe.width > 0 && pulledOut.width < 0 {
// setPulledOutWith = CGFloat(0)
// } else if (mainSwipe.width < 0 && pulledOut.width < 0) ||
// (mainSwipe.width < 0 && pulledOut.width == 0) {
// setPulledOutWith = pulledOutRight
// setDragOffset = margin + setPulledOutWith
// } else if abs(mainSwipe.width + pulledOut.width) > 30 {
// setPulledOutWith = pulledOutLeft
// }
withAnimation(.spring(response: 0.2)) {
pulledOut.width = finalSwipe
dragOffset = setDragOffset
mainSwipe = .zero
}
} }
) )
.onChange(of: scrollDelegate.isScrolling) { value in
print ("pop reset change")
// if scrollDelegate.isScrolling == true {
Task {
mainSwipe.width = 0
}
// }
}
} }
} }
.background(Color(red: 0.1, green: 0.1, blue: 0.1)) .background(Color(red: 0.1, green: 0.1, blue: 0.1))
} }
func onDragEnded() {
print("pop ended")
paneConnector.disableScroll = false
var finalSwipe = CGFloat(0)
let swipeLeftFinal = CGFloat(-200)
let swipeRightFinal = CGFloat(110)
let margin = CGFloat(30)
var setDragOffset = CGFloat(0)
if startSwipeState == .center {
if startSwipeDir == .right {
finalSwipe = swipeRightFinal
} else {
finalSwipe = swipeLeftFinal
setDragOffset = margin + swipeLeftFinal
}
} else if startSwipeState == .right {
finalSwipe = .zero
if startSwipeDir == .left {
finalSwipe = .zero
} else {
finalSwipe = swipeRightFinal
}
} else if startSwipeState == .left {
if startSwipeDir == .left {
finalSwipe = swipeLeftFinal
setDragOffset = margin + swipeLeftFinal
} else {
finalSwipe = .zero
}
}
startSwipeState = nil
startSwipeDir = nil
print("foo")
// if mainSwipe.width < 0 && pulledOut.width > 0 {
// setPulledOutWith = CGFloat(0)
// } else if mainSwipe.width > 0 && pulledOut.width < 0 {
// setPulledOutWith = CGFloat(0)
// } else if (mainSwipe.width < 0 && pulledOut.width < 0) ||
// (mainSwipe.width < 0 && pulledOut.width == 0) {
// setPulledOutWith = pulledOutRight
// setDragOffset = margin + setPulledOutWith
// } else if abs(mainSwipe.width + pulledOut.width) > 30 {
// setPulledOutWith = pulledOutLeft
// }
withAnimation(.spring(response: 0.2)) {
pulledOut.width = finalSwipe
dragOffset = setDragOffset
mainSwipe = .zero
}
}
// let hackyPinch = MagnificationGesture(minimumScaleDelta: 0.0)
// .onChanged({ delta in
// onDragEnded()
// })
// .onEnded({ delta in
// onDragEnded()
// })
// let hackyRotation = RotationGesture(minimumAngleDelta: Angle(degrees: 0.0))
// .onChanged({ delta in
// onDragEnded()
// })
// .onEnded({ delta in
// onDragEnded()
// })
// let hackyPress = LongPressGesture(minimumDuration: 0.0, maximumDistance: 0.0)
// .onChanged({ _ in
// onDragEnded()
// })
// .onEnded({ delta in
// onDragEnded()
// })
func handleVisibilityChanged2(_: String, change _: VisibilityChange, tracker _: VisibilityTracker<String>) {} func handleVisibilityChanged2(_: String, change _: VisibilityChange, tracker _: VisibilityTracker<String>) {}
func rubberBandEffect(_ offset: CGFloat) -> CGFloat { func rubberBandEffect(_ offset: CGFloat) -> CGFloat {
let resistance: CGFloat = 0.55 let resistance: CGFloat = 0.05
return resistance * pow(abs(offset), 0.7) * (offset < 0 ? -1 : 1) return 6 * log(offset + 1)
// return resistance * pow(abs(offset), 1) * (offset < 0 ? -1 : 1)
}
private func dragCancelled() {
print("pop dragCancelled")
mainSwipe = .zero
} }
} }