gloss-ios/gloss/ContentView.swift

688 lines
22 KiB
Swift
Raw Normal View History

//
// ContentView.swift
// gloss
//
// Created by Saint on 10/23/22.
//
import GRDB
import GRDBQuery
import os
2024-05-15 08:57:41 -07:00
import SwiftUI
2024-05-16 13:08:52 -07:00
import SwiftUIIntrospect
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "network")
2024-05-15 08:57:41 -07:00
var currentId: String?
var currentOffset: CGFloat?
2023-04-23 20:41:17 -07:00
2023-08-16 12:19:14 -07:00
var disableDrop = false
2024-06-12 09:19:30 -07:00
//TODO: move to globals file
let mainBackgroundColor = Color(red: 0.1, green: 0.1, blue: 0.1)
let mainTextColor = Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00))
let secondBackgroundColor = Color(red: 0.18, green: 0.18, blue: 0.18)
2024-05-15 08:57:41 -07:00
public extension UserDefaults {
func optionalInt(forKey defaultName: String) -> Int? {
2023-02-28 14:03:58 -08:00
let defaults = self
if let value = defaults.value(forKey: defaultName) {
return value as? Int
}
2024-05-15 08:57:41 -07:00
return nil
2023-02-28 14:03:58 -08:00
}
2024-05-15 08:57:41 -07:00
func optionalBool(forKey defaultName: String) -> Bool? {
2023-02-28 14:03:58 -08:00
let defaults = self
if let value = defaults.value(forKey: defaultName) {
return value as? Bool
}
return nil
}
}
2024-06-03 15:26:56 -07:00
func createUndoState(selectedRibbon: Ribbon,
appDatabase : AppDatabase,
paneConnector : PaneConnector) async throws -> [Ribbon]
2024-05-31 10:04:43 -07:00
{
2024-06-03 15:26:56 -07:00
let updateThreshold = 30
2024-05-31 10:04:43 -07:00
var updatedRibbon = selectedRibbon
var scrollOffsetToSave = Int(floor(paneConnector.currentOffset))
var scrollIdToSave = paneConnector.currentId
2024-06-03 15:26:56 -07:00
2024-05-31 10:04:43 -07:00
var offsetDiff = abs(scrollOffsetToSave - updatedRibbon.scrollOffset) > 30
2024-06-03 15:26:56 -07:00
2024-05-31 10:04:43 -07:00
var idDiff = Int(updatedRibbon.scrollId) != Int(scrollIdToSave)
if idDiff || offsetDiff {
updatedRibbon.scrollId = scrollIdToSave
updatedRibbon.scrollOffset = scrollOffsetToSave
print("meow bumping")
let ret = try await appDatabase.bumpRibbon(&updatedRibbon)
return ret
}
print("meow no bump")
return []
}
2023-11-14 13:39:46 -08:00
func goToRibbon(selectedRibbon: Ribbon,
destRibbon: Ribbon,
2023-06-01 12:45:36 -07:00
appDatabase: AppDatabase,
paneConnector: PaneConnector,
2024-06-03 20:08:35 -07:00
loading: Bool)
2023-06-01 12:45:36 -07:00
{
2024-05-31 10:04:43 -07:00
print("meow goto ribbon - selected ribbon: \(selectedRibbon), dest ribbon: \(destRibbon) ")
2023-05-31 13:57:17 -07:00
DispatchQueue.main.asyncAfter(deadline: .now()) {
Task {
var scrollOffsetToSave = paneConnector.currentOffset
var scrollIdToSave = paneConnector.currentId
2023-05-31 13:57:17 -07:00
print("go to ribbon")
print("\(selectedRibbon.id) \(destRibbon.id!)")
2023-11-14 13:39:46 -08:00
2024-06-03 15:26:56 -07:00
// if selectedRibbon.id != destRibbon.id! || loading {
if true {
print("switching ribbons")
2023-05-31 13:57:17 -07:00
paneConnector.showOverlay = true
if loading {
paneConnector.currentId = destRibbon.scrollId
}
paneConnector.scrollId = destRibbon.scrollId
paneConnector.scrollOffset = CGFloat(destRibbon.scrollOffset)
paneConnector.refresh.toggle()
print("toggling")
print("paneconnector: \(paneConnector.refresh)")
2023-06-01 12:45:36 -07:00
var updateSelectRibbon = SelectedRibbon(id: Int64(1), ribbonGroupId: Int64(destRibbon.groupId))
// print("Saving selected ribbon")
// print(updateSelectRibbon)
do {
_ = try await appDatabase.saveSelectedRibbon(&updateSelectRibbon)
} catch {
// Print("something wrong")
}
2023-05-31 13:57:17 -07:00
}
2023-06-01 12:45:36 -07:00
}
2023-05-31 13:57:17 -07:00
}
2023-05-31 13:57:17 -07:00
}
2023-11-14 13:39:46 -08:00
2023-08-03 12:40:12 -07:00
extension View {
@ViewBuilder
func `if`<Transform: View>(_ condition: Bool, transform: (Self) -> Transform) -> some View {
if condition { transform(self) }
else { self }
}
}
2023-05-31 13:57:17 -07:00
2024-05-15 08:57:41 -07:00
struct RibbonCrown: View {
2023-03-01 10:47:34 -08:00
var ribbon: Ribbon
@ObservedObject var paneConnector: PaneConnector
2024-05-15 08:57:41 -07:00
var draggedRibbon: Ribbon?
var isDragging: Bool
2023-02-28 14:03:58 -08:00
2024-06-07 08:24:33 -07:00
var height = CGFloat(41)
var width = CGFloat(70)
var scale = 0.70
2023-07-21 17:19:30 -07:00
2023-02-28 14:03:58 -08:00
@Environment(\.appDatabase) private var appDatabase
2024-05-31 10:04:43 -07:00
@Query(SelectedRibbonRequest()) private var selectedRibbon: [Ribbon]
2023-02-28 14:03:58 -08:00
@State var saveOffset = CGFloat()
2024-05-23 11:41:16 -07:00
@Binding var refresh: Bool
var body: some View {
ZStack {
2023-11-14 13:39:46 -08:00
MyIcon().frame(
width: CGFloat(100 * 1.66 * scale),
height: CGFloat(100 * scale),
alignment: .center
2024-05-15 08:57:41 -07:00
).foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4)))
.contentShape(.dragPreview, RoundedRectangle(cornerRadius: 32))
2023-11-14 13:39:46 -08:00
.if(draggedRibbon != nil && draggedRibbon!.id == ribbon.id && isDragging) { $0.overlay(Color(red: 0.1, green: 0.1, blue: 0.1)) }
2023-11-14 13:39:46 -08:00
Text(ribbon.title)
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
2024-06-07 08:24:33 -07:00
.frame(minWidth: width,
maxWidth: width,
2024-05-15 08:57:41 -07:00
minHeight: height,
maxHeight: height,
alignment: .center)
2023-08-03 12:40:12 -07:00
2023-11-14 13:39:46 -08:00
.if(draggedRibbon != nil && draggedRibbon!.id == ribbon.id && isDragging) { $0.overlay(Color(red: 0.1, green: 0.1, blue: 0.1)) }
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
.multilineTextAlignment(.center)
// .minimumScaleFactor(0.5)
// .padding([.top, .bottom], 10)
.font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(10)))
}
2024-05-20 10:53:47 -07:00
.onTapGesture {
Task {
2024-05-31 10:04:43 -07:00
let sr = selectedRibbon[0]
2024-06-03 15:26:56 -07:00
let updatedRibbon = try await createUndoState(selectedRibbon: sr,
appDatabase: appDatabase,
paneConnector: paneConnector)
if sr.id == ribbon.id {
paneConnector.scrollId = paneConnector.currentId
paneConnector.scrollOffset = paneConnector.currentOffset
paneConnector.hasMoved = false
} else {
goToRibbon(selectedRibbon: sr,
destRibbon: ribbon,
appDatabase: appDatabase,
paneConnector: paneConnector,
2024-06-03 20:08:35 -07:00
loading: false)
2024-06-03 15:26:56 -07:00
}
}
2024-05-20 10:53:47 -07:00
}
2024-05-15 08:57:41 -07:00
.frame(width: CGFloat(100 * 1.66 * scale + 10), height: CGFloat(100 * scale + 5))
2023-03-01 10:47:34 -08:00
}
}
2023-02-28 14:03:58 -08:00
2024-06-07 08:24:33 -07:00
// object used for JSON decoding of verses
2023-03-11 20:31:48 -08:00
class Verse: NSObject, Codable {
var body: String
var verse: Int
}
func makeVerseView(seg: SegDenorm) -> some View {
var retView = Text("")
var segSplit = seg.body.components(separatedBy: ";;")
let decoder = JSONDecoder()
2024-05-15 08:57:41 -07:00
for (index, item) in segSplit.enumerated() {
2023-03-11 20:31:48 -08:00
let verse = try! decoder.decode(Verse.self, from: item.data(using: .utf8)!)
retView = retView + Text(String(verse.verse))
2024-05-15 08:57:41 -07:00
.font(Font.custom("AveriaSerifLibre-Regular", size: 6))
.baselineOffset(6.0)
.foregroundColor(Color.white)
2023-03-11 20:31:48 -08:00
retView = retView + Text(verse.body)
2024-05-15 08:57:41 -07:00
.foregroundColor(Color.white)
.font(Font.custom("AveriaSerifLibre-Regular", size: 15))
}
2023-03-11 20:31:48 -08:00
return retView
}
2023-03-01 10:47:34 -08:00
class PaneConnector: NSObject, ObservableObject {
2024-06-23 16:36:21 -07:00
2024-05-20 13:40:32 -07:00
var showOverlay: Bool = false
@Published var refresh: Bool = false
@Published var vertSep = CGFloat(20)
2024-05-21 09:20:23 -07:00
var currentId = ""
var currentOffset = CGFloat()
var visibilityTracker: VisibilityTracker<String>?
2024-05-31 11:23:36 -07:00
@Published var scrollId = ""
@Published var scrollOffset = CGFloat()
2024-06-03 15:26:56 -07:00
@Published var hasMoved = false
2024-05-21 09:20:23 -07:00
var setScrollOffset: CGFloat?
2024-06-23 16:36:21 -07:00
@Published var disableScroll = false
2024-06-03 15:26:56 -07:00
2024-05-23 07:46:13 -07:00
}
2024-05-20 13:40:32 -07:00
2024-06-23 16:36:21 -07:00
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()
}
}
2024-05-15 08:57:41 -07:00
struct ContentView: View {
2024-05-20 13:24:00 -07:00
// this is for the whole view swiping
2024-06-07 08:24:33 -07:00
@State var mainSwipe = CGSize.zero
@State var pulledOut = CGSize.zero
2023-02-28 14:03:58 -08:00
@State var selection = 0
@StateObject var paneConnector = PaneConnector()
2024-06-23 16:36:21 -07:00
@StateObject var scrollDelegate = ScrollDelegate()
2024-05-20 13:40:32 -07:00
@State var refresh: Bool = false
2023-02-28 14:03:58 -08:00
@State var readOffset = CGPoint()
2023-11-14 13:39:46 -08:00
2024-05-26 07:45:30 -07:00
@Query(SegDenormRequest(book: "bible.john")) private var segs: [SegDenorm]
2023-11-14 13:39:46 -08:00
@State var draggedRibbon: Ribbon?
2023-08-03 12:40:12 -07:00
@State var isDragging = false
2023-11-14 13:39:46 -08:00
2024-06-03 20:08:35 -07:00
@State var dragOffset = CGFloat(0)
2024-06-23 16:36:21 -07:00
@GestureState var dragGestureActive = CGSize.zero
2024-06-08 15:53:23 -07:00
enum SwipeStartState {
case center
case right
case left
}
enum SwipeStartDir {
case left
case right
}
// @State var curSwipeState: SwipeState = .start
@State var startSwipeState: SwipeStartState?
@State var startSwipeDir: SwipeStartDir?
2024-05-20 13:40:32 -07:00
@Environment(\.appDatabase) private var appDatabase
2024-05-23 07:46:13 -07:00
@Query(RibbonRequest()) private var ribbons: [Ribbon]
2023-06-01 12:45:36 -07:00
@Query<SelectedRibbonRequest> var selectedRibbon: [Ribbon]
init() {
UITableView.appearance().backgroundColor = UIColor(Color(red: 0.2, green: 0.2, blue: 0.2))
2024-05-15 08:57:41 -07:00
_selectedRibbon = Query(SelectedRibbonRequest())
2024-06-23 16:36:21 -07:00
}
2023-11-14 13:39:46 -08:00
2024-06-23 16:36:21 -07:00
var body: some View {
2023-03-11 20:31:48 -08:00
2024-06-23 16:36:21 -07:00
var fontSize = CGFloat(15)
var scale = 0.65
var height = CGFloat(50)
2023-07-21 17:19:30 -07:00
2023-07-31 10:54:42 -07:00
var width = CGFloat(100 * 1.66 * scale)
GeometryReader { geometry in
2024-05-15 08:57:41 -07:00
ZStack(alignment: .top) {
VStack(alignment: .leading) {
2023-07-21 17:19:30 -07:00
VStack {
2024-06-07 08:24:33 -07:00
ForEach(ribbons) { ribbon in
RibbonCrown(ribbon: ribbon,
paneConnector: paneConnector,
2023-08-03 12:40:12 -07:00
draggedRibbon: draggedRibbon,
2024-05-23 11:41:16 -07:00
isDragging: isDragging,
refresh: $refresh)
2024-05-16 13:08:52 -07:00
.onDrag {
2024-05-15 08:57:41 -07:00
self.draggedRibbon = ribbon
return NSItemProvider()
2024-05-16 13:08:52 -07:00
}
2024-05-15 08:57:41 -07:00
.onDrop(of: [.item],
delegate: DropViewDelegate(destinationItem: ribbon,
draggedItem: $draggedRibbon,
isDragging: $isDragging,
appDatabase: appDatabase))
.offset(x: 6, y: 6)
2023-07-31 10:54:42 -07:00
}
2023-07-21 17:19:30 -07:00
}
.frame(width: geometry.size.width, height: geometry.size.height - 100, alignment: .topLeading)
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
.zIndex(0)
.animation(.default, value: ribbons)
2023-08-03 15:22:18 -07:00
.onDrop(of: [.item],
2024-05-15 08:57:41 -07:00
delegate: DropViewDelegate2(isDragging: $isDragging))
}
2023-03-11 20:31:48 -08:00
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
2023-07-21 17:19:30 -07:00
.frame(alignment: .topLeading)
2024-05-31 10:04:43 -07:00
VStack {
NaviBar(paneConnector: paneConnector)
StatsPanel(paneConnector: paneConnector)
2024-06-07 08:24:33 -07:00
.offset(y:20)
2024-05-31 10:04:43 -07:00
}
2024-06-07 08:24:33 -07:00
// .frame(maxWidth: 300)
.offset(x: geometry.size.width - 300)
2023-07-21 17:19:30 -07:00
VStack {
// Top pane
2024-06-03 20:08:35 -07:00
Pane(paneConnector: paneConnector,
2024-06-23 16:36:21 -07:00
scrollDelegate: scrollDelegate,
2024-05-23 09:19:18 -07:00
selectedRibbon: selectedRibbon,
2024-06-07 08:24:33 -07:00
width: geometry.size.width - 15,
height: geometry.size.height + 20,
2024-06-03 20:08:35 -07:00
dragOffset: dragOffset)
2023-07-21 17:19:30 -07:00
2024-06-07 08:24:33 -07:00
///////////////////////////////////
// Text("separator").foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
// .gesture(
// DragGesture()
// .onChanged { gesture in
// paneConnector.vertSep = paneConnector.vertSep - gesture.translation.height
// }
2024-06-23 16:36:21 -07:00
//
2024-06-07 08:24:33 -07:00
// // Bottom pane
// ScrollViewReader { _ in
// VisibilityTrackingScrollView(action: handleVisibilityChanged2) {
// // ScrollView {
// LazyVStack {
// ForEach(segs) { seg in
// SegRow(seg: seg,
// ribbonId: selectedRibbon[0].id!)
// .id("\(seg.id)")
// .padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20))
// .trackVisibility(id: "\(seg.id)")
// }
// }
// .background(Color(red: 0.18, green: 0.18, blue: 0.18))
// }
// .onAppear {
// Print("APPEAR")
// }
// .listStyle(PlainListStyle())
// }
// .zIndex(1)
// .background(Color(red: 0.2, green: 0.2, blue: 0.2))
2023-06-27 16:04:24 -07:00
2024-06-07 08:24:33 -07:00
///////////////////////////////////
2024-05-20 10:53:47 -07:00
}
2024-06-07 08:24:33 -07:00
.offset(x: 20, y: 0)
2024-05-20 10:53:47 -07:00
.offset(x: pulledOut.width)
2024-06-08 15:53:23 -07:00
.offset(x: mainSwipe.width)
2024-06-23 16:36:21 -07:00
.highPriorityGesture(
2024-06-23 21:53:15 -07:00
DragGesture(minimumDistance: 20)
2024-06-23 16:36:21 -07:00
.updating($dragGestureActive) { value, state, _ in
print("pop here")
state = value.translation
}
2024-06-08 15:53:23 -07:00
.onChanged { value in
2024-06-23 16:36:21 -07:00
print("pop changed")
2024-06-08 15:53:23 -07:00
// Calculate the offset
2024-06-09 07:32:59 -07:00
let margin = CGFloat(30)
2024-06-08 15:53:23 -07:00
var newOffset = value.translation.width
if startSwipeState == nil {
if pulledOut.width == 0 {
startSwipeState = .center
} else if pulledOut.width < 0 {
startSwipeState = .left
} else {
startSwipeState = .right
}
2024-05-20 10:53:47 -07:00
2024-06-08 15:53:23 -07:00
print("start swipe meow: \(startSwipeState)")
2024-06-08 16:41:44 -07:00
}
2024-06-23 16:36:21 -07:00
if newOffset > 0 {
startSwipeDir = .right
} else {
startSwipeDir = .left
}
2024-06-07 08:24:33 -07:00
2024-06-08 15:53:23 -07:00
// Apply resistance if out of bounds
2024-06-23 21:53:15 -07:00
let maxRight: CGFloat = 140
let finalRight: CGFloat = 110
let rightDiff = maxRight - finalRight
2024-06-23 16:36:21 -07:00
var maxOffsetLeft: CGFloat = -200
2024-06-23 21:53:15 -07:00
if newOffset > maxRight , pulledOut.width == 0 {
// newOffset = maxRight + rubberBandEffect(newOffset)
newOffset = maxRight + rubberBandEffect(newOffset - maxRight)
2024-06-08 16:41:44 -07:00
}
2024-06-23 21:53:15 -07:00
if newOffset > rightDiff, pulledOut.width > 0 {
newOffset = rightDiff + rubberBandEffect(newOffset - rightDiff)
2024-06-23 16:36:21 -07:00
}
2024-06-23 16:36:21 -07:00
if newOffset < maxOffsetLeft, pulledOut.width == 0 {
newOffset = maxOffsetLeft + rubberBandEffect(newOffset)
2024-06-08 15:53:23 -07:00
}
2024-06-07 08:24:33 -07:00
2024-06-08 15:53:23 -07:00
self.mainSwipe.width = newOffset
2024-06-07 08:24:33 -07:00
// dragOffset is what is used to make the text be readable
// with the right pane being visible
2024-06-23 16:36:21 -07:00
if mainSwipe.width < -margin, pulledOut.width <= 0 {
2024-06-09 07:32:59 -07:00
dragOffset = margin + mainSwipe.width + pulledOut.width
}
2024-06-08 15:53:23 -07:00
2024-06-23 16:36:21 -07:00
if mainSwipe.width > 0, pulledOut.width < 0 {
2024-06-09 07:32:59 -07:00
dragOffset = margin + mainSwipe.width + pulledOut.width
}
2024-05-20 10:53:47 -07:00
}
.onEnded { _ in
2024-06-23 16:36:21 -07:00
onDragEnded()
}
)
.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))
}
2024-06-08 15:53:23 -07:00
2024-06-23 16:36:21 -07:00
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
2024-06-08 15:53:23 -07:00
2024-06-23 16:36:21 -07:00
if startSwipeDir == .left {
finalSwipe = .zero
} else {
finalSwipe = swipeRightFinal
}
} else if startSwipeState == .left {
if startSwipeDir == .left {
finalSwipe = swipeLeftFinal
setDragOffset = margin + swipeLeftFinal
} else {
finalSwipe = .zero
}
}
2024-06-23 16:36:21 -07:00
startSwipeState = nil
startSwipeDir = nil
2024-06-07 08:24:33 -07:00
2024-06-23 16:36:21 -07:00
print("foo")
2024-06-12 09:19:30 -07:00
2024-06-23 16:36:21 -07:00
// if mainSwipe.width < 0 && pulledOut.width > 0 {
// setPulledOutWith = CGFloat(0)
// } else if mainSwipe.width > 0 && pulledOut.width < 0 {
// setPulledOutWith = CGFloat(0)
2024-06-08 15:53:23 -07:00
2024-06-23 16:36:21 -07:00
// } 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
// }
2024-06-23 16:36:21 -07:00
withAnimation(.spring(response: 0.2)) {
pulledOut.width = finalSwipe
dragOffset = setDragOffset
mainSwipe = .zero
}
}
2024-06-23 16:36:21 -07:00
// 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()
// })
2024-05-15 08:57:41 -07:00
func handleVisibilityChanged2(_: String, change _: VisibilityChange, tracker _: VisibilityTracker<String>) {}
2024-06-08 15:53:23 -07:00
2024-06-23 21:53:15 -07:00
2024-06-08 15:53:23 -07:00
func rubberBandEffect(_ offset: CGFloat) -> CGFloat {
2024-06-23 16:36:21 -07:00
let resistance: CGFloat = 0.05
2024-06-23 21:53:15 -07:00
return 6 * log(offset + 1)
2024-06-23 16:36:21 -07:00
// return resistance * pow(abs(offset), 1) * (offset < 0 ? -1 : 1)
}
private func dragCancelled() {
print("pop dragCancelled")
mainSwipe = .zero
2024-06-08 15:53:23 -07:00
}
}
private let itemFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .medium
return formatter
}()
2023-08-03 15:22:18 -07:00
struct DropViewDelegate2: DropDelegate {
@Binding var isDragging: Bool
2024-05-15 08:57:41 -07:00
func dropUpdated(info _: DropInfo) -> DropProposal? {
2023-08-03 15:22:18 -07:00
return DropProposal(operation: .move)
}
2024-05-15 08:57:41 -07:00
func performDrop(info _: DropInfo) -> Bool {
2023-08-04 12:02:22 -07:00
isDragging = false
2023-08-03 15:22:18 -07:00
return true
}
2024-05-15 08:57:41 -07:00
func dropEntered(info _: DropInfo) {
2023-08-03 15:22:18 -07:00
isDragging = true
print("SECOND DROPPPOOO")
}
}
struct DropViewDelegate: DropDelegate {
let destinationItem: Ribbon
// @Binding var colors: [Color]
@Binding var draggedItem: Ribbon?
2023-08-03 12:40:12 -07:00
@Binding var isDragging: Bool
let appDatabase: AppDatabase
2023-11-14 13:39:46 -08:00
2024-05-15 08:57:41 -07:00
func dropUpdated(info _: DropInfo) -> DropProposal? {
return DropProposal(operation: .move)
}
2024-05-15 08:57:41 -07:00
func dropExited(info _: DropInfo) {
2023-08-03 12:40:12 -07:00
print("EXITED")
isDragging = false
}
2024-05-15 08:57:41 -07:00
func dropEntered(info _: DropInfo) {
Task {
2023-08-03 12:40:12 -07:00
isDragging = true
2024-05-15 08:57:41 -07:00
if draggedItem == nil {
2023-08-03 12:40:12 -07:00
return
}
2023-11-14 13:39:46 -08:00
if disableDrop {
2024-05-15 08:57:41 -07:00
return
2023-11-14 13:39:46 -08:00
}
2023-08-16 12:19:14 -07:00
2023-11-14 13:39:46 -08:00
var newRibbon = draggedItem!
var newDest = destinationItem
var oldPos = draggedItem!.pos
var newPos = destinationItem.pos
print("dragged item")
print(draggedItem)
print("dest item")
print(destinationItem)
2024-05-15 08:57:41 -07:00
if draggedItem!.id! == destinationItem.id! {
return
}
newRibbon.pos = destinationItem.pos
2024-05-15 08:57:41 -07:00
_ = try await appDatabase.updateRibbonPosition(&newRibbon, oldPos, newPos)
2023-08-16 12:19:14 -07:00
disableDrop = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
disableDrop = false
}
2023-08-03 12:40:12 -07:00
draggedItem!.pos = newPos
2023-08-03 12:40:12 -07:00
// draggedItem = nil
}
}
2023-11-14 13:39:46 -08:00
2024-05-15 08:57:41 -07:00
func performDrop(info _: DropInfo) -> Bool {
2023-08-03 12:40:12 -07:00
print("PERFORMED DROPPPP")
draggedItem = nil
2023-08-03 12:40:12 -07:00
isDragging = false
return true
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
ContentView().environment(\.appDatabase, .random())
}
}
extension View {
2024-05-23 07:46:13 -07:00
@discardableResult
func Print(_ vars: Any...) -> some View {
2024-05-15 08:57:41 -07:00
for v in vars {
print(v)
}
return EmptyView()
}
}