gloss-ios/gloss/ContentView.swift

942 lines
40 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
2024-05-15 08:57:41 -07:00
import WrappingHStack
2024-05-16 13:08:52 -07:00
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
var gTracker: VisibilityTracker<String>?
2023-06-01 12:45:36 -07:00
var printCount: Int64 = 0
2023-04-23 20:41:17 -07:00
2023-08-16 12:19:14 -07:00
var disableDrop = false
// var curBook = "John"
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
}
}
2023-11-14 13:39:46 -08:00
func goToRibbon(selectedRibbon: Ribbon,
destRibbon: Ribbon,
2023-05-31 13:57:17 -07:00
scrollId: Binding<String?>,
scrollOffset: Binding<CGFloat?>,
refresh: Binding<Bool>,
2023-06-27 16:04:24 -07:00
showOverlay: Binding<Bool>,
2023-06-01 12:45:36 -07:00
appDatabase: AppDatabase,
2024-05-15 08:57:41 -07:00
loading: Bool)
2023-06-01 12:45:36 -07:00
{
Task {
2023-11-14 13:39:46 -08:00
// print("SELECTED RIBBON", selectedRibbon)
2023-05-31 13:57:17 -07:00
var scrollOffsetToSave = currentOffset
var scrollIdToSave = currentId
var updatedRibbon = selectedRibbon
2024-05-15 08:57:41 -07:00
if selectedRibbon.id != destRibbon.id! || loading {
print("switching ribbons")
2023-11-14 13:39:46 -08:00
2023-06-27 16:04:24 -07:00
// withAnimation(.spring(response: 0.05)) {
2024-05-15 08:57:41 -07:00
// showOverlay.wrappedValue = true
showOverlay.wrappedValue = true
2023-06-27 16:04:24 -07:00
// }
2023-05-31 13:57:17 -07:00
2024-05-15 08:57:41 -07:00
if loading {
2023-06-01 12:45:36 -07:00
currentId = destRibbon.scrollId
// currentOffset = CGFloat(destRibbon.scrollOffset)
}
2023-05-31 13:57:17 -07:00
scrollId.wrappedValue = destRibbon.scrollId
// print("setting scroll offset")
2023-05-31 13:57:17 -07:00
scrollOffset.wrappedValue = CGFloat(destRibbon.scrollOffset)
// print(scrollOffset.wrappedValue)
// print("end setting scroll offset")
2023-05-31 13:57:17 -07:00
refresh.wrappedValue.toggle()
var updateSelectRibbon = SelectedRibbon(id: Int64(1), ribbonId: destRibbon.id!)
// print("Saving selected ribbon")
// print(updateSelectRibbon)
2023-05-31 13:57:17 -07:00
do {
_ = try await appDatabase.saveSelectedRibbon(&updateSelectRibbon)
2024-05-15 08:57:41 -07:00
} catch {
2023-05-31 13:57:17 -07:00
// Print("something wrong")
}
}
2024-05-15 08:57:41 -07:00
if !loading {
2023-06-01 12:45:36 -07:00
print("not loading")
2023-06-27 16:04:24 -07:00
updatedRibbon.scrollOffset = Int(floor(scrollOffsetToSave!))
2023-06-01 12:45:36 -07:00
updatedRibbon.scrollId = scrollIdToSave!
2023-05-31 13:57:17 -07:00
2023-06-01 12:45:36 -07:00
_ = try await appDatabase.saveRibbon(&updatedRibbon)
// print("saved updatedRibbon", updatedRibbon)
2023-05-31 13:57:17 -07:00
2023-06-01 12:45:36 -07:00
// print("UPDATED")
// scrollOffsetToSave = userDefaults.object(forKey: "currentOffset") as? CGFloat
// scrollIdToSave = userDefaults.object(forKey: "currentId") as? String
} else {
print("loading")
}
2023-05-31 13:57:17 -07:00
// print("scrollOffsetToSave: ", scrollOffsetToSave)
// print("scrollIdToSave: ", scrollIdToSave)
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
2024-05-15 08:57:41 -07:00
@Binding var scrollId: String?
@Binding var scrollOffset: CGFloat?
@Binding var showOverlay: Bool
@Binding var refresh: Bool
var draggedRibbon: Ribbon?
var isDragging: Bool
2023-02-28 14:03:58 -08:00
var height = CGFloat(45)
2023-07-21 17:19:30 -07:00
var xOffset = CGFloat(25)
var scale = 0.65
2023-02-28 14:03:58 -08:00
@Environment(\.appDatabase) private var appDatabase
2023-03-01 10:47:34 -08:00
@Query(SelectedRibbonRequest()) private var sr: [Ribbon]
2023-02-28 14:03:58 -08:00
@State var saveOffset = CGFloat()
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)) }
2024-05-15 08:57:41 -07:00
// .offset(x: 10)
2023-08-03 12:40:12 -07:00
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)))
// .foregroundColor(.white))
// .foregroundColor(.black)
.frame(minWidth: CGFloat(70),
2024-05-15 08:57:41 -07:00
maxWidth: CGFloat(70),
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)) }
2023-08-03 12:40:12 -07:00
2023-11-14 13:39:46 -08:00
// .if(!isDragging || draggedRibbon == nil || draggedRibbon!.id != ribbon.id) { $0.background(Color(red: 0.1, green: 0.1, blue: 0.1)) }
// .if(draggedRibbon != nil && draggedRibbon!.id == ribbon.id) { $0.background(.red) }
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
// .offset(x: 10)
// .background(Color(red: 0.1, green: 0.1, blue: 0.1))
// .background(.red)
// .background(.yellow)
.multilineTextAlignment(.center)
// .minimumScaleFactor(0.5)
// .padding([.top, .bottom], 10)
.font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(10)))
}
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
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
2023-03-11 20:31:48 -08:00
private struct SegRow: View {
var seg: SegDenorm
2023-06-01 12:45:36 -07:00
var ribbonId: Int64
2024-05-16 12:49:27 -07:00
@State var highlights = Set<Int>()
2023-03-01 10:47:34 -08:00
2024-05-16 13:08:52 -07:00
var body: some View {
var segSplit = seg.body.components(separatedBy: ";;")
let decoder = JSONDecoder()
2024-05-16 08:39:38 -07:00
var retView = WrappingHStack(alignment: .leading, horizontalSpacing: 0) {
2024-05-16 13:08:52 -07:00
ForEach(0 ..< segSplit.count, id: \.self) { segIndex in
let verse = try! decoder.decode(Verse.self, from: segSplit[segIndex].data(using: .utf8)!)
let arrayOfText = verse.body.components(separatedBy: " ")
2024-05-15 08:57:41 -07:00
2024-05-16 08:39:38 -07:00
let lineHeight = CGFloat(30)
let fontSize = CGFloat(20)
2024-05-16 12:49:27 -07:00
let highlightColor = "470000"
2024-05-16 13:08:52 -07:00
ForEach(0 ..< arrayOfText.count, id: \.self) { index in
HStack(spacing: 0) {
if index == 0 {
2024-05-16 08:39:38 -07:00
Text("")
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
2024-05-16 08:39:38 -07:00
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
2024-05-16 13:08:52 -07:00
.if(self.highlights.contains(verse.verse)) { $0.background(Color(hex: highlightColor)) }
2024-05-16 08:39:38 -07:00
2024-05-16 13:08:52 -07:00
VStack(spacing: 0) {
2024-05-16 08:39:38 -07:00
ZStack {
Text(" ")
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
2024-05-16 13:08:52 -07:00
.if(self.highlights.contains(verse.verse)) { $0.background(Color(hex: highlightColor)) }
2024-05-16 08:39:38 -07:00
Text(String(verse.verse))
.font(Font.custom("AveriaSerifLibre-Regular", size: 10))
.padding(.horizontal, 0)
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
2024-05-16 13:08:52 -07:00
.if(self.highlights.contains(verse.verse)) { $0.background(Color(hex: highlightColor)) }
2024-05-16 08:39:38 -07:00
}
2024-05-16 13:08:52 -07:00
.if(self.highlights.contains(verse.verse)) { $0.background(Color(hex: highlightColor)) }
2024-05-16 08:39:38 -07:00
}
}
Text(arrayOfText[index])
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
2024-05-16 08:39:38 -07:00
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
.padding(.horizontal, 1.5) // intra word spacing
2024-05-16 13:08:52 -07:00
.if(self.highlights.contains(verse.verse)) { $0.background(Color(hex: highlightColor)) }
.foregroundColor(Color.white)
.onTapGesture {
Print(arrayOfText[index])
2024-05-16 08:39:38 -07:00
Print(verse.verse)
2024-05-16 12:49:27 -07:00
if self.highlights.contains(verse.verse) {
self.highlights.remove(verse.verse)
} else {
self.highlights.insert(verse.verse)
}
}
2024-05-15 08:57:41 -07:00
}
2024-05-16 13:08:52 -07:00
.frame(height: 16) // intra line spacing
.padding(.vertical, 0)
// .if( index == 0 ) { $0.offset(x: -6) }
}
2024-05-15 08:57:41 -07:00
}
}
return retView
}
}
2024-05-15 08:57:41 -07:00
struct ContentView: View {
@State var viewState = CGSize.zero
@State var pulledOut = CGSize.zero
2024-05-15 08:57:41 -07:00
@State var taskTitle: String = "FIRST DOGGG"
@State var curBook: String = "Matthew"
@State var selectedLine: Int64?
2023-02-28 14:03:58 -08:00
2024-05-15 08:57:41 -07:00
@State var thisScrollView: UIScrollView?
2023-03-11 20:31:48 -08:00
@State var scrollUpdate = false
2023-03-01 10:47:34 -08:00
@State var initLoad = false
2023-04-21 17:06:30 -07:00
// set this to scroll to area
2024-05-15 08:57:41 -07:00
@State var scrollId: String?
@State var scrollOffset: CGFloat?
2023-04-21 17:06:30 -07:00
2024-05-15 08:57:41 -07:00
@State var setScrollOffset: CGFloat?
@State var showOverlay: Bool = false
2023-07-21 17:19:30 -07:00
@State var vertSep = CGFloat(20)
2023-06-01 12:45:36 -07:00
@Environment(\.appDatabase) private var appDatabase
2023-03-11 20:31:48 -08:00
@Query(SegDenormRequest(book: "bible.mark")) private var segs: [SegDenorm]
2023-04-21 17:06:30 -07:00
// @State var scrollDelegate: ScrollViewHandler
2023-03-11 20:31:48 -08:00
// @State var scrollDelegate = ScrollViewHandler()
2023-03-01 10:47:34 -08:00
2023-02-28 14:03:58 -08:00
// @State var selectedRibbonId = Int64(UserDefaults.standard.optionalInt(forKey: "selectedRibbonId") ?? 1)
2023-03-01 10:47:34 -08:00
// ribbon
2023-06-01 12:45:36 -07:00
// @Query(SelectedRibbonRequest()) private var selectedRibbon: [Ribbon]
2023-02-28 14:03:58 -08:00
@State var endedDrag = true
@State var readOffset = CGPoint()
2023-07-21 17:19:30 -07:00
@State var dragOffset = CGFloat()
2023-11-14 13:39:46 -08:00
2023-03-11 20:31:48 -08:00
@State var refresh: Bool = false
2023-06-01 12:45:36 -07:00
@State var refresh2: Bool = false
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
@State var reorder = true
@Query(RibbonRequest()) private var ribbons: [Ribbon]
2023-06-01 12:45:36 -07:00
@Query<SelectedRibbonRequest> var selectedRibbon: [Ribbon]
2023-02-28 14:03:58 -08:00
// @Query(RibbonRequest(id: Int64(UserDefaults.standard.optionalInt(forKey: "lastRibbonId") ?? 1))) private var selectedRibbon: [Ribbon]
2023-11-14 13:39:46 -08:00
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())
2023-06-01 12:45:36 -07:00
2023-04-21 17:06:30 -07:00
// self._scrollDelegate = State(initialValue: ScrollViewHandler())
}
2023-11-14 13:39:46 -08:00
var body: some View {
// Print("rendering")
2023-03-11 20:31:48 -08:00
var size1 = CGFloat(11)
var size2 = CGFloat(100)
var fontSize = CGFloat(15)
var scale = 0.65
var height = CGFloat(50)
var xOffset = CGFloat(25)
2023-07-21 17:19:30 -07:00
2023-07-31 10:54:42 -07:00
var width = CGFloat(100 * 1.66 * scale)
// ForEach(ribbons) { ribbon in
// data.append(ribbon)
// }
2023-07-31 10:54:42 -07:00
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 {
// ReorderableForEach($data, allowReordering: $reorder) { item, isDragged in
ForEach(ribbons) { ribbon in
RibbonCrown(ribbon: ribbon,
2024-05-15 08:57:41 -07:00
scrollId: $scrollId,
scrollOffset: $scrollOffset,
showOverlay: $showOverlay,
2024-05-15 08:57:41 -07:00
refresh: $refresh,
2023-08-03 12:40:12 -07:00
draggedRibbon: draggedRibbon,
2024-05-15 08:57:41 -07:00
isDragging: isDragging)
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
2023-07-31 10:54:42 -07:00
// .foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.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-08-03 15:22:18 -07:00
2023-07-21 17:19:30 -07:00
// Spacer()
2023-03-11 20:31:48 -08:00
// ForEach(ribbons) { ribbon in
// RibbonCrown(ribbon: ribbon,
// scrollId:$scrollId,
// scrollOffset:$scrollOffset,
// showOverlay: $showOverlay,
// refresh:$refresh
// )
// // .buttonStyle(BlueButtonStyle())
// // .frame(alignment: .topLeading)
// // .background(Color(red: 0.4, green: 0.4, blue: 0.1))
// .animation(nil)
// }
}
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-15 08:57:41 -07:00
// .animation(nil)
2023-07-21 17:19:30 -07:00
VStack {
ScrollViewReader { proxy in
VisibilityTrackingScrollView(action: handleVisibilityChanged) {
// ScrollView {
LazyVStack {
ForEach(segs) { seg in
SegRow(seg: seg,
2024-05-15 08:57:41 -07:00
ribbonId: selectedRibbon[0].id!)
.id("\(seg.id)")
.offset(x: -dragOffset)
// .offset(x: pulledOut.width)
2023-07-21 17:19:30 -07:00
2024-05-15 08:57:41 -07:00
.padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20))
.trackVisibility(id: "\(seg.id)")
2023-07-21 17:19:30 -07:00
// .onChange(of: geometry.frame(in: .named("scrollView"))) { imageRect in
2024-05-15 08:57:41 -07:00
// Print(imageRect)
// Print(outerProxy)
2023-07-21 17:19:30 -07:00
// if isInView(innerRect: imageRect, isIn: outerProxy) {
// visibleIndex.insert(item)
2024-05-15 08:57:41 -07:00
// } else {
2023-07-21 17:19:30 -07:00
// visibleIndex.remove(item)
// }
// }
}
2023-06-27 16:04:24 -07:00
}
2023-07-21 17:19:30 -07:00
.background(Color(red: 0.18, green: 0.18, blue: 0.18))
}
2023-06-01 12:45:36 -07:00
2024-05-15 08:57:41 -07:00
.onAppear {
2023-07-21 17:19:30 -07:00
Print("APPEAR")
// Print(selectedRibbon[0])
// scrollId = "3"
// scrollOffset = 103
// refresh.toggle()
goToRibbon(selectedRibbon: selectedRibbon[0],
destRibbon: selectedRibbon[0],
scrollId: $scrollId,
scrollOffset: $scrollOffset,
refresh: $refresh,
showOverlay: $showOverlay,
appDatabase: appDatabase,
loading: true)
}
2024-05-15 08:57:41 -07:00
.onChange(of: refresh) { _ in
// if let target = target {
// gTracker!.visibleViews["123123"] = CGFloat(100)
2023-07-21 17:19:30 -07:00
// Print("ON CHANGE", gTracker!.visibleViews)
// Print("removing", gTracker!.visibleViews.removeAll())
2023-06-01 12:45:36 -07:00
2023-07-21 17:19:30 -07:00
Task {
DispatchQueue.main.async {
Print("scroll Id target: \(scrollId)")
2024-05-15 08:57:41 -07:00
proxy.scrollTo(scrollId!, anchor: .top)
2023-07-21 17:19:30 -07:00
// proxy.scrollTo(String(Int(scrollId!)! + 1))
// currentId = scrollId!
// if (currentId != scrollId!) {
2023-06-02 14:25:20 -07:00
2023-07-21 17:19:30 -07:00
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
Print(" scroll id target", scrollId)
Print(" current id ", currentId)
Print(gTracker!.sortedViewIDs)
2024-05-15 08:57:41 -07:00
if currentId! != scrollId! {
2023-07-21 17:19:30 -07:00
Print("NO MATCH")
}
2023-06-02 14:25:20 -07:00
2023-07-21 17:19:30 -07:00
// Print(" scroll offset target", scrollOffset)
Print(" current offset ", gTracker!.visibleViews[scrollId!])
var curOffset = gTracker!.visibleViews[scrollId!]
Print(" stats", gTracker!.visibleViews)
// // setScrollOffset = CGFloat(Int(currentOffset!) * -1 + Int(scrollOffset!))
2024-05-15 08:57:41 -07:00
if curOffset != nil {
2023-07-21 17:19:30 -07:00
setScrollOffset = CGFloat(Int(scrollOffset!) - Int(curOffset!))
Print("applying scroll offset \(setScrollOffset)")
// // setScrollOffset = CGFloat(Int(scrollOffset!))
// Print("setting scroll offset", setScrollOffset)
refresh2.toggle()
} else {
var adjust = (Int(scrollId!)! - Int(currentId!)!) * 200
Print("adjusting \(adjust)")
2023-06-02 14:25:20 -07:00
2023-07-21 17:19:30 -07:00
setScrollOffset = CGFloat(adjust)
refresh.toggle()
}
// // currentId = scrollId!
2023-06-02 14:25:20 -07:00
2023-07-21 17:19:30 -07:00
// DispatchQueue.main.async {
2023-06-02 14:25:20 -07:00
2023-07-21 17:19:30 -07:00
// currentOffset = scrollOffset!
// currentId = scrollId!
// }
}
2023-06-27 16:04:24 -07:00
}
2023-06-02 14:25:20 -07:00
}
2023-04-21 17:06:30 -07:00
}
2024-05-16 13:08:52 -07:00
.introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { scrollView in Print("introspect")
2024-05-15 08:57:41 -07:00
// Print("Scroll delegate offset", scrollDelegate.scrollOffset)
2023-07-21 17:19:30 -07:00
2024-05-15 08:57:41 -07:00
if setScrollOffset != nil {
2023-07-21 17:19:30 -07:00
// Print("Setting scroll offset in introspect", setScrollOffset)
2023-11-14 13:39:46 -08:00
DispatchQueue.main.async {
2023-07-21 17:19:30 -07:00
scrollView.contentOffset.y = scrollView.contentOffset.y + setScrollOffset!
setScrollOffset = nil
2024-05-15 08:57:41 -07:00
// self.showOverlay = false
2023-07-21 17:19:30 -07:00
withAnimation {
showOverlay = false
}
}
}
// if (thisScrollView == nil) {
// Print("init scroll")
// thisScrollView = scrollView
// scrollView.contentOffset.y = CGFloat(selectedRibbon[0].scrollOffset)
// }
Print("end introspect")
}
.listStyle(PlainListStyle())
2023-06-02 14:25:20 -07:00
}
2023-07-21 17:19:30 -07:00
.zIndex(1)
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
2023-11-14 13:39:46 -08:00
.frame(width: geometry.size.width - 50, height: geometry.size.height / 2 - vertSep)
2024-05-15 08:57:41 -07:00
.offset(x: 30, y: 0)
2023-07-21 17:19:30 -07:00
.offset(x: pulledOut.width)
.offset(x: viewState.width, y: viewState.height)
.gesture(
DragGesture()
2024-05-15 08:57:41 -07:00
.onChanged { gesture in
2023-07-21 17:19:30 -07:00
2024-05-15 08:57:41 -07:00
if endedDrag {
endedDrag = false
scrollOffset = readOffset.y - 20
// _ = Print("meow")
2023-06-27 16:04:24 -07:00
}
2024-05-15 08:57:41 -07:00
// logger.error("hello222")
// NSLog("hellooo")
Print(viewState.width)
if abs(gesture.translation.width) > 20 {
viewState.width = gesture.translation.width
if gesture.translation.width < -50, pulledOut.width == CGFloat(0) {
dragOffset = gesture.translation.width + 50
}
}
// offset.y = gesture.translation.width
// logger.log("hello")
2023-06-27 16:04:24 -07:00
}
2024-05-15 08:57:41 -07:00
.onEnded { _ in
endedDrag = true
var pulledOutWidth = CGFloat(0)
if viewState.width < 0 {
pulledOutWidth = CGFloat(0)
} else if abs(viewState.width + pulledOut.width) > 30 {
pulledOutWidth = CGFloat(200)
}
2023-06-02 14:25:20 -07:00
2024-05-15 08:57:41 -07:00
withAnimation(.spring(response: 0.2)) {
pulledOut.width = pulledOutWidth
viewState = .zero
dragOffset = .zero
}
2023-07-21 17:19:30 -07:00
}
)
2024-05-15 08:57:41 -07:00
Text("separator").foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
.gesture(
DragGesture()
.onChanged { gesture in
2023-07-21 17:19:30 -07:00
2024-05-15 08:57:41 -07:00
vertSep = vertSep - gesture.translation.height
Print(gesture.translation.width)
Print(gesture.translation.height)
Print("drag")
// if (endedDrag) {
// endedDrag = false
// scrollOffset = readOffset.y - 20
// // _ = Print("meow")
// }
//// logger.error("hello222")
//// NSLog("hellooo")
// Print(viewState.width)
// if (abs(gesture.translation.width) > 20) {
// viewState.width = gesture.translation.width
// }
////offset.y = gesture.translation.width
//// logger.log("hello")
}
// .onEnded { _ in
// endedDrag = true
// var pulledOutWidth = CGFloat(0)
// if (viewState.width < 0) {
// pulledOutWidth = CGFloat(0)
// }
// else if abs(viewState.width + pulledOut.width ) > 30 {
// pulledOutWidth = CGFloat(200)
// }
// withAnimation(.spring(response: 0.2)) {
// pulledOut.width = pulledOutWidth
// viewState = .zero
// }
// }
)
ScrollViewReader { _ in
2023-07-21 17:19:30 -07:00
VisibilityTrackingScrollView(action: handleVisibilityChanged2) {
// ScrollView {
LazyVStack {
ForEach(segs) { seg in
SegRow(seg: seg,
2024-05-15 08:57:41 -07:00
ribbonId: selectedRibbon[0].id!)
.id("\(seg.id)")
.padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20))
.trackVisibility(id: "\(seg.id)")
2023-07-21 17:19:30 -07:00
// .onChange(of: geometry.frame(in: .named("scrollView"))) { imageRect in
2024-05-15 08:57:41 -07:00
// Print(imageRect)
// Print(outerProxy)
2023-07-21 17:19:30 -07:00
// if isInView(innerRect: imageRect, isIn: outerProxy) {
// visibleIndex.insert(item)
2024-05-15 08:57:41 -07:00
// } else {
2023-07-21 17:19:30 -07:00
// visibleIndex.remove(item)
// }
// }
}
}
.background(Color(red: 0.18, green: 0.18, blue: 0.18))
}
2023-06-27 16:04:24 -07:00
2024-05-15 08:57:41 -07:00
.onAppear {
2023-07-21 17:19:30 -07:00
Print("APPEAR")
// Print(selectedRibbon[0])
// scrollId = "3"
// scrollOffset = 103
// refresh.toggle()
// goToRibbon(selectedRibbon: selectedRibbon[0],
// destRibbon: selectedRibbon[0],
// scrollId: $scrollId,
// scrollOffset: $scrollOffset,
// refresh: $refresh,
// showOverlay: $showOverlay,
// appDatabase: appDatabase,
// loading: true)
2023-02-28 14:03:58 -08:00
}
2024-05-15 08:57:41 -07:00
// .onChange(of: refresh) { target in
2023-07-21 17:19:30 -07:00
// //if let target = target {
// //gTracker!.visibleViews["123123"] = CGFloat(100)
// // Print("ON CHANGE", gTracker!.visibleViews)
// // Print("removing", gTracker!.visibleViews.removeAll())
// Task {
// DispatchQueue.main.async {
// Print("scroll Id target: \(scrollId)")
// proxy.scrollTo(scrollId! , anchor: .top)
// // proxy.scrollTo(String(Int(scrollId!)! + 1))
// // currentId = scrollId!
// // if (currentId != scrollId!) {
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// Print(" scroll id target", scrollId)
// Print(" current id ", currentId)
// Print(gTracker!.sortedViewIDs)
// if (currentId! != scrollId!) {
// Print("NO MATCH")
// }
// // Print(" scroll offset target", scrollOffset)
// Print(" current offset ", gTracker!.visibleViews[scrollId!])
// var curOffset = gTracker!.visibleViews[scrollId!]
// Print(" stats", gTracker!.visibleViews)
// // // setScrollOffset = CGFloat(Int(currentOffset!) * -1 + Int(scrollOffset!))
// if (curOffset != nil) {
// setScrollOffset = CGFloat(Int(scrollOffset!) - Int(curOffset!))
// Print("applying scroll offset \(setScrollOffset)")
// // // setScrollOffset = CGFloat(Int(scrollOffset!))
// // Print("setting scroll offset", setScrollOffset)
// refresh2.toggle()
// } else {
// var adjust = (Int(scrollId!)! - Int(currentId!)!) * 200
// Print("adjusting \(adjust)")
// setScrollOffset = CGFloat(adjust)
// refresh.toggle()
// }
// // // currentId = scrollId!
// // DispatchQueue.main.async {
// // currentOffset = scrollOffset!
// // currentId = scrollId!
// // }
// }
// }
// }
2024-05-15 08:57:41 -07:00
// }
// .introspectScrollView { scrollView in
2023-07-21 17:19:30 -07:00
// Print("introspect")
// // scrollView.delegate = scrollDelegate
// //Print("Scroll delegate offset", scrollDelegate.scrollOffset)
// if (setScrollOffset != nil) {
// // Print("Setting scroll offset in introspect", setScrollOffset)
2023-11-14 13:39:46 -08:00
// DispatchQueue.main.async {
2023-07-21 17:19:30 -07:00
// scrollView.contentOffset.y = scrollView.contentOffset.y + setScrollOffset!
// setScrollOffset = nil
// withAnimation {
// showOverlay = false
// }
// }
// }
// // if (thisScrollView == nil) {
// // Print("init scroll")
// // thisScrollView = scrollView
// // scrollView.contentOffset.y = CGFloat(selectedRibbon[0].scrollOffset)
// // }
// Print("end instrospect")
2024-05-15 08:57:41 -07:00
// }
2023-07-21 17:19:30 -07:00
.listStyle(PlainListStyle())
}
2023-07-21 17:19:30 -07:00
.zIndex(1)
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
.frame(width: geometry.size.width - 50)
2024-05-15 08:57:41 -07:00
.offset(x: 30, y: 0)
2023-07-21 17:19:30 -07:00
.offset(x: pulledOut.width)
.offset(x: viewState.width, y: viewState.height)
.gesture(
DragGesture()
2024-05-15 08:57:41 -07:00
.onChanged { gesture in
2023-07-21 17:19:30 -07:00
2024-05-15 08:57:41 -07:00
if endedDrag {
endedDrag = false
scrollOffset = readOffset.y - 20
// _ = Print("meow")
}
// logger.error("hello222")
// NSLog("hellooo")
Print(viewState.width)
if abs(gesture.translation.width) > 20 {
viewState.width = gesture.translation.width
}
// offset.y = gesture.translation.width
// logger.log("hello")
2023-07-21 17:19:30 -07:00
}
2024-05-15 08:57:41 -07:00
.onEnded { _ in
endedDrag = true
var pulledOutWidth = CGFloat(0)
if viewState.width < 0 {
pulledOutWidth = CGFloat(0)
} else if abs(viewState.width + pulledOut.width) > 30 {
pulledOutWidth = CGFloat(200)
}
2024-05-15 08:57:41 -07:00
withAnimation(.spring(response: 0.2)) {
pulledOut.width = pulledOutWidth
viewState = .zero
}
2023-07-21 17:19:30 -07:00
}
)
}
2023-06-27 16:04:24 -07:00
2024-05-15 08:57:41 -07:00
if showOverlay {
2023-06-27 16:04:24 -07:00
Rectangle()
2023-11-14 13:39:46 -08:00
.frame(width: geometry.size.width - 50, height: geometry.size.height + 200)
.background(.ultraThinMaterial)
2023-06-27 16:04:24 -07:00
2024-05-15 08:57:41 -07:00
// .blur(radius: 0.8)
.offset(x: 30, y: -100)
2023-11-14 13:39:46 -08:00
.opacity(0.98)
.transition(.opacity)
2023-06-27 16:04:24 -07:00
2023-11-14 13:39:46 -08:00
// .frame(width: geometry.size.width - 50)
.offset(x: pulledOut.width)
.offset(x: viewState.width, y: viewState.height)
.zIndex(2)
2023-06-27 16:04:24 -07:00
}
}
}
}
2024-05-15 08:57:41 -07:00
func handleVisibilityChanged2(_: String, change _: VisibilityChange, tracker _: VisibilityTracker<String>) {}
2024-05-15 08:57:41 -07:00
func handleVisibilityChanged(_: String, change _: VisibilityChange, tracker: VisibilityTracker<String>) {
2023-06-02 14:25:20 -07:00
// var printRate: Int64 = 10
2023-06-01 12:45:36 -07:00
gTracker = tracker
2023-04-21 17:06:30 -07:00
// @Environment(\.appDatabase) var appDatabase
// switch change {
// case .shown: print("\(id) shown")
// case .hidden: print("\(id) hidden")
// }
2023-06-02 14:25:20 -07:00
// if (printCount % printRate == 0) {
// print("VISIBILITY CHANGED STARTED")
// print(tracker.visibleViews)
// print(tracker.sortedViewIDs)
// print("VISIBILITY CHANGED ENDED")
// }
// printCount += 1
2023-06-01 12:45:36 -07:00
2023-11-14 13:39:46 -08:00
// if (currentId != nil) {
2023-04-21 17:06:30 -07:00
// currentOffset = tracker.visibleViews[currentId!]!
// }
2023-04-23 20:41:17 -07:00
let visibleViews2 = Array(tracker.visibleViews.keys)
2024-05-15 08:57:41 -07:00
if visibleViews2.count == 0 {
return
}
2023-06-02 16:20:04 -07:00
// currentId = tracker.sortedViewIDs[tracker.sortedViewIDs.count - 1]
currentId = tracker.sortedViewIDs[0]
2023-06-02 14:25:20 -07:00
currentOffset = tracker.visibleViews[currentId!]!
2023-06-02 16:20:04 -07:00
// if (Int(currentOffset!) != -1 && Int(currentOffset!) < 0) {
// if (tracker.sortedViewIDs.count > 1) {
// currentId = tracker.sortedViewIDs[1]
// currentOffset = tracker.visibleViews[currentId!]!
// }
// }
2024-05-15 08:57:41 -07:00
// if (currentId != nil) {
// // if (printCount % printRate == 0) {
// // print(printCount)
// // print("cat current ID:", currentId)
// // }
// // print("got here")
// currentOffset = tracker.visibleViews[currentId!]!
// }
}
}
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 {
func Print(_ vars: Any...) -> some View {
2024-05-15 08:57:41 -07:00
for v in vars {
print(v)
}
return EmptyView()
}
}