split views with drag working

undo
Saint 2023-07-21 20:19:30 -04:00
parent ea019551a8
commit b6caadb16f
8 changed files with 525 additions and 320 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -14,8 +14,8 @@
filePath = "gloss/ContentView.swift" filePath = "gloss/ContentView.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "566" startingLineNumber = "565"
endingLineNumber = "566" endingLineNumber = "565"
landmarkName = "body" landmarkName = "body"
landmarkType = "24"> landmarkType = "24">
</BreakpointContent> </BreakpointContent>
@ -30,8 +30,8 @@
filePath = "gloss/ContentView.swift" filePath = "gloss/ContentView.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "568" startingLineNumber = "567"
endingLineNumber = "568" endingLineNumber = "567"
landmarkName = "body" landmarkName = "body"
landmarkType = "24"> landmarkType = "24">
</BreakpointContent> </BreakpointContent>
@ -46,8 +46,8 @@
filePath = "gloss/ContentView.swift" filePath = "gloss/ContentView.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "459" startingLineNumber = "458"
endingLineNumber = "459" endingLineNumber = "458"
landmarkName = "body" landmarkName = "body"
landmarkType = "24"> landmarkType = "24">
</BreakpointContent> </BreakpointContent>
@ -62,8 +62,8 @@
filePath = "gloss/ContentView.swift" filePath = "gloss/ContentView.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "427" startingLineNumber = "426"
endingLineNumber = "427" endingLineNumber = "426"
landmarkName = "body" landmarkName = "body"
landmarkType = "24"> landmarkType = "24">
</BreakpointContent> </BreakpointContent>

View File

@ -52,6 +52,7 @@ struct AppDatabase {
try db.create(table: "Ribbon") { t in try db.create(table: "Ribbon") { t in
t.autoIncrementedPrimaryKey("id") t.autoIncrementedPrimaryKey("id")
t.column("title", .text).notNull()
t.column("book", .text).notNull() t.column("book", .text).notNull()
t.column("scrollOffset", .integer).notNull() t.column("scrollOffset", .integer).notNull()
t.column("scrollId", .text) t.column("scrollId", .text)
@ -68,7 +69,7 @@ struct AppDatabase {
t.column("scrollOffset", .integer).notNull() t.column("scrollOffset", .integer).notNull()
} }
try db.create(table: "foo3") { t in try db.create(table: "foo4") { t in
t.autoIncrementedPrimaryKey("id") t.autoIncrementedPrimaryKey("id")
t.column("ribbonId", .integer).notNull() t.column("ribbonId", .integer).notNull()
} }
@ -140,38 +141,34 @@ extension AppDatabase {
} }
func importJson(_ filename: String, _ db: Database) throws {
let importJson : JsonImport = load(filename)
if try Line.all().isEmpty(db) {
for l in importJson.lines {
print("importing Lines")
_ = try l.inserted(db)
}
for l in importJson.segs {
print("importing SEGS")
_ = try l.inserted(db)
}
}
}
/// Create random Lines if the database is empty. /// Create random Lines if the database is empty.
func createRandomLinesIfEmpty() throws { func initDatabase() throws {
let imports : JsonImport = load("john_export.json")
try dbWriter.write { db in try dbWriter.write { db in
// try db.execute(sql: "DELETE FROM Line")
// try db.execute(sql: "DELETE FROM Seg")
// try db.execute(sql: "DELETE FROM Ribbon")
// try db.execute(sql: "DELETE FROM SelectedRibbon")
if try Line.all().isEmpty(db) { if try Line.all().isEmpty(db) {
for l in imports.lines {
print("here")
print(l.body)
_ = try l.inserted(db)
}
for l in imports.segs { try importJson("john_export.json", db)
print("here SEGS") try importJson("mark_export.json", db)
print(l.seg_id) _ = try Ribbon(id: 1, title: "John", book: "bible.john", scrollId: "1", scrollOffset: 0).inserted(db)
_ = try l.inserted(db) _ = try Ribbon(id: 2, title: "Gospel of Mark", book: "bible.mark", scrollId: "1", scrollOffset: 300).inserted(db)
}
// print("cat")
// try createRandomLines(db)
_ = try Ribbon(id: 1, book: "bible.john", scrollId: "1", scrollOffset: 0).inserted(db)
_ = try Ribbon(id: 2, book: "bible.john", scrollId: "1", scrollOffset: 300).inserted(db)
_ = try SelectedRibbon(id: 1, ribbonId: 1).inserted(db) _ = try SelectedRibbon(id: 1, ribbonId: 1).inserted(db)
} }
} }

View File

@ -43,7 +43,7 @@ struct BlueButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View { func makeBody(configuration: Self.Configuration) -> some View {
configuration.label configuration.label
.font(.headline) .font(.headline)
.frame(width: 160) .frame(width: 100)
.contentShape(Rectangle()) .contentShape(Rectangle())
.foregroundColor(configuration.isPressed ? Color.white.opacity(0.5) : Color.black) .foregroundColor(configuration.isPressed ? Color.white.opacity(0.5) : Color.black)
.background(configuration.isPressed ? Color.purple.opacity(0.5) : Color.purple) .background(configuration.isPressed ? Color.purple.opacity(0.5) : Color.purple)
@ -119,13 +119,17 @@ func goToRibbon(selectedRibbon: Ribbon,
} }
} }
struct SwitchButton : View { struct RibbonCrown : View {
var ribbon: Ribbon var ribbon: Ribbon
@Binding var scrollId : String? @Binding var scrollId : String?
@Binding var scrollOffset : CGFloat? @Binding var scrollOffset : CGFloat?
@Binding var showOverlay : Bool @Binding var showOverlay : Bool
@Binding var refresh : Bool @Binding var refresh : Bool
var height = CGFloat(50)
var xOffset = CGFloat(25)
var scale = 0.65
@Environment(\.appDatabase) private var appDatabase @Environment(\.appDatabase) private var appDatabase
@Query(SelectedRibbonRequest()) private var sr: [Ribbon] @Query(SelectedRibbonRequest()) private var sr: [Ribbon]
@ -133,24 +137,47 @@ struct SwitchButton : View {
@State var saveOffset = CGFloat() @State var saveOffset = CGFloat()
var body: some View { var body: some View {
// ForEach(sr) { selectedRibbon in Text(ribbon.title)
let ribbonString = String(sr[0].id!) + " " + String(ribbon.id!) + " " + String(ribbon.scrollOffset) + " " + ribbon.scrollId .foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
Button(ribbonString, // // .background(Color(red: 0.3, green: 0.3, blue: 0.3))
action: { // .foregroundColor(.white))
Task { // .foregroundColor(.black)
goToRibbon(selectedRibbon: sr[0], .frame(minWidth: CGFloat(75), maxWidth: CGFloat(75), minHeight: height, maxHeight: height, alignment: .center)
destRibbon: ribbon, // .background(.red)
scrollId: $scrollId, // .background(.yellow)
scrollOffset: $scrollOffset, .multilineTextAlignment(.center)
refresh: $refresh, // .minimumScaleFactor(0.5)
showOverlay: $showOverlay, .padding([.top, .bottom], 10)
appDatabase: appDatabase, .font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(10)))
loading: false)
}
}
) .overlay( MyIcon().frame(width: CGFloat(100 * 1.66 * scale), height: CGFloat(100 * scale), alignment: .center) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))))
.buttonStyle(BlueButtonStyle())
.offset(x: xOffset)
.onTapGesture {
Print("TAP")
// selectedLine = seg.id
// Print(selectedLine)
}
// ForEach(sr) { selectedRibbon in
// let ribbonString = String(sr[0].id!) + " " + String(ribbon.id!) + " " + String(ribbon.scrollOffset) + " " + ribbon.scrollId
// Button(ribbonString,
// action: {
// Task {
// goToRibbon(selectedRibbon: sr[0],
// destRibbon: ribbon,
// scrollId: $scrollId,
// scrollOffset: $scrollOffset,
// refresh: $refresh,
// showOverlay: $showOverlay,
// appDatabase: appDatabase,
// loading: false)
// }
// }
// )
// .buttonStyle(BlueButtonStyle())
} }
} }
@ -261,6 +288,8 @@ struct ContentView: View {
@State var setScrollOffset: CGFloat? @State var setScrollOffset: CGFloat?
@State var showOverlay: Bool = false @State var showOverlay: Bool = false
@State var vertSep = CGFloat(20)
@Environment(\.appDatabase) private var appDatabase @Environment(\.appDatabase) private var appDatabase
@Query(SegDenormRequest(book: "bible.mark")) private var segs: [SegDenorm] @Query(SegDenormRequest(book: "bible.mark")) private var segs: [SegDenorm]
@ -276,6 +305,7 @@ struct ContentView: View {
@State var endedDrag = true @State var endedDrag = true
@State var readOffset = CGPoint() @State var readOffset = CGPoint()
@State var dragOffset = CGFloat()
@State var refresh: Bool = false @State var refresh: Bool = false
@ -304,287 +334,485 @@ struct ContentView: View {
var scale = 0.65 var scale = 0.65
var height = CGFloat(50) var height = CGFloat(50)
var xOffset = CGFloat(25) var xOffset = CGFloat(25)
GeometryReader { geometry in GeometryReader { geometry in
ZStack (alignment: .top) { ZStack (alignment: .top) {
VStack (alignment: .leading) {
VStack {
Text("Imitation of Christ")
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
// // .background(Color(red: 0.3, green: 0.3, blue: 0.3))
// .foregroundColor(.white))
// .foregroundColor(.black)
.frame(minWidth: CGFloat(75), maxWidth: CGFloat(75), minHeight: height, maxHeight: height, alignment: .center)
// .background(.red)
// .background(.yellow)
.multilineTextAlignment(.center)
// .minimumScaleFactor(0.5)
.padding([.top, .bottom], 10)
.font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(10)))
.overlay( MyIcon().frame(width: CGFloat(100 * 1.66 * scale), height: CGFloat(100 * scale), alignment: .center) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))))
VStack{ .offset(x: xOffset)
.onTapGesture {
Print("TAP")
// selectedLine = seg.id
// Print(selectedLine)
}
// .offset(y: 25)
Text("Imitation of Christ") Text("Psalms")
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00))) .foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
// // .background(Color(red: 0.3, green: 0.3, blue: 0.3)) // .background(Color(red: 0.3, green: 0.3, blue: 0.3))
// .foregroundColor(.white)) // .foregroundColor(.white))
// .foregroundColor(.black) // .foregroundColor(.black)
.frame(minWidth: CGFloat(75), maxWidth: CGFloat(75), minHeight: height, maxHeight: height, alignment: .center) .overlay( MyIcon().frame(width: CGFloat(100 * 1.66 * scale), height: CGFloat(100 * scale)) .foregroundColor(Color(UIColor(red: 0.56, green: 0.30, blue: 0.30, alpha: 0.4))))
// .background(.red) .frame(minWidth: CGFloat(75), maxWidth: CGFloat(75), minHeight: height, maxHeight: height, alignment: .center)
// .background(.yellow) // .background(.red)
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
// .minimumScaleFactor(0.5)
.padding([.top, .bottom], 10)
.font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(10)))
.overlay( MyIcon().frame(width: CGFloat(100 * 1.66 * scale), height: CGFloat(100 * scale), alignment: .center) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4)))) .offset(x: xOffset)
.padding([.top, .bottom], 10)
// .minimumScaleFactor(0.5)
.font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(14)))
.offset(x: xOffset) // Text("padding")
// .offset(y: 25)
Text("Psalms") Text("Fundamentals of Dogmatic Theology")
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00))) .foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
// .background(Color(red: 0.3, green: 0.3, blue: 0.3)) // .background(Color(red: 0.3, green: 0.3, blue: 0.3))
// .foregroundColor(.white)) // .foregroundColor(.black)
// .foregroundColor(.black) .overlay( MyIcon().frame(width: CGFloat(100 * 1.66 * scale), height: CGFloat(100 * scale)) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))))
.overlay( MyIcon().frame(width: CGFloat(100 * 1.66 * scale), height: CGFloat(100 * scale)) .foregroundColor(Color(UIColor(red: 0.56, green: 0.30, blue: 0.30, alpha: 0.4)))) .frame(minWidth: CGFloat(75), maxWidth: CGFloat(75), minHeight: height, maxHeight: height, alignment: .center)
.frame(minWidth: CGFloat(75), maxWidth: CGFloat(75), minHeight: height, maxHeight: height, alignment: .center) // .background(.red)
// .background(.red) .multilineTextAlignment(.center)
.multilineTextAlignment(.center) .padding([.top, .bottom], 10)
.offset(x: xOffset)
// .minimumScaleFactor(0.5)
.font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(10)))
// .minimumScaleFactor(0.9)
.offset(x: xOffset) // Text("padding")
.padding([.top, .bottom], 10)
// .minimumScaleFactor(0.5)
.font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(14)))
// Text("padding") }
.frame(width: geometry.size.width, height: geometry.size.height - 100, alignment: .topLeading)
Text("Fundamentals of Dogmatic Theology") .background(Color(red: 0.1, green: 0.1, blue: 0.1))
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00))) .zIndex(0)
// .background(Color(red: 0.3, green: 0.3, blue: 0.3))
// .foregroundColor(.black)
.overlay( MyIcon().frame(width: CGFloat(100 * 1.66 * scale), height: CGFloat(100 * scale)) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))))
.frame(minWidth: CGFloat(75), maxWidth: CGFloat(75), minHeight: height, maxHeight: height, alignment: .center)
// .background(.red)
.multilineTextAlignment(.center)
.padding([.top, .bottom], 10)
.offset(x: xOffset)
// .minimumScaleFactor(0.5)
.font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(10)))
// .minimumScaleFactor(0.9)
// Text("padding")
// // Text("Fundamentals of Dogmatic Theology")
// Text("FoDT")
// .font(Font.custom("AveriaSerifLibre-Regular", size: CGFloat(15)))
// .foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
// // .backgroundColor(Color(UIColor(red: 1.00, green: 0.76, blue: 0.76, alpha: 1.00)))
// // .background(Color(red: 0.3, green: 0.3, blue: 0.3))
// .overlay( MyIcon().frame(width: size2, height: size2) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))))
// // .background(.yellow)
// // .foregroundColor(.white))
// .frame(width: CGFloat(50), height: CGFloat(80))
// .lineLimit(nil)
// .multilineTextAlignment(.leading)
// .minimumScaleFactor(0.9)
// Text("Jn")
// .font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
// .foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
// // .background(Color(red: 0.3, green: 0.3, blue: 0.3))
// .overlay( MyIcon().frame(width: size1, height: size1) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))))
// // .foregroundColor(.white))
// .frame(width: size2, height: size2)
// Text("MTW")
// .font(Font.custom("AveriaSerifLibre-Regular", size: 20))
// .foregroundColor(Color.white)
// .overlay( MyCustomShape().frame(width: 120, height: 100))
// .frame(width: 120, height: 120)
// Spacer()
ForEach(ribbons) { ribbon in ForEach(ribbons) { ribbon in
SwitchButton(ribbon: ribbon, RibbonCrown(ribbon: ribbon,
scrollId:$scrollId, scrollId:$scrollId,
scrollOffset:$scrollOffset, scrollOffset:$scrollOffset,
showOverlay: $showOverlay, showOverlay: $showOverlay,
refresh:$refresh refresh:$refresh
) )
.buttonStyle(BlueButtonStyle()) // .buttonStyle(BlueButtonStyle())
// Print("RIBBON") // .frame(alignment: .topLeading)
// Print(ribbon)
// .background(Color(red: 0.4, green: 0.4, blue: 0.1))
.animation(nil)
} }
} }
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
.background(Color(red: 0.1, green: 0.1, blue: 0.1)) .background(Color(red: 0.1, green: 0.1, blue: 0.1))
.zIndex(0) .frame(alignment: .topLeading)
.animation(nil)
ScrollViewReader { proxy in VStack {
VisibilityTrackingScrollView(action: handleVisibilityChanged) {
// ScrollView {
LazyVStack { ScrollViewReader { proxy in
Text(refresh ? "Selected" : "not Selected") VisibilityTrackingScrollView(action: handleVisibilityChanged) {
Button("Jump to #8") { // ScrollView {
scrollId = "20"
} LazyVStack {
ForEach(segs) { seg in ForEach(segs) { seg in
SegRow(seg: seg, SegRow(seg: seg,
ribbonId: selectedRibbon[0].id! ribbonId: selectedRibbon[0].id!
) )
.id("\(seg.id)") .id("\(seg.id)")
.offset(x: -dragOffset)
// .offset(x: pulledOut.width)
.padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20)) .padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20))
.trackVisibility(id: "\(seg.id)") .trackVisibility(id: "\(seg.id)")
// .onChange(of: geometry.frame(in: .named("scrollView"))) { imageRect in // .onChange(of: geometry.frame(in: .named("scrollView"))) { imageRect in
//Print(imageRect) //Print(imageRect)
//Print(outerProxy) //Print(outerProxy)
// if isInView(innerRect: imageRect, isIn: outerProxy) { // if isInView(innerRect: imageRect, isIn: outerProxy) {
// visibleIndex.insert(item) // visibleIndex.insert(item)
// } else { // } else {
// visibleIndex.remove(item) // visibleIndex.remove(item)
// } // }
// }
}
}
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
}
.onAppear() {
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)
}
.onChange(of: refresh) { target in
//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!
// } // }
} }
} }
.background(Color(red: 0.18, green: 0.18, blue: 0.18))
} }
}
.introspectScrollView { scrollView in
Print("introspect")
// scrollView.delegate = scrollDelegate
//Print("Scroll delegate offset", scrollDelegate.scrollOffset)
if (setScrollOffset != nil) { .onAppear() {
// Print("Setting scroll offset in introspect", setScrollOffset) Print("APPEAR")
DispatchQueue.main.async { // Print(selectedRibbon[0])
scrollView.contentOffset.y = scrollView.contentOffset.y + setScrollOffset! // scrollId = "3"
setScrollOffset = nil // scrollOffset = 103
withAnimation { // refresh.toggle()
showOverlay = false
goToRibbon(selectedRibbon: selectedRibbon[0],
destRibbon: selectedRibbon[0],
scrollId: $scrollId,
scrollOffset: $scrollOffset,
refresh: $refresh,
showOverlay: $showOverlay,
appDatabase: appDatabase,
loading: true)
}
.onChange(of: refresh) { target in
//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!
// }
}
} }
} }
} }
.introspectScrollView { scrollView in
Print("introspect")
// scrollView.delegate = scrollDelegate
//Print("Scroll delegate offset", scrollDelegate.scrollOffset)
// if (thisScrollView == nil) { if (setScrollOffset != nil) {
// Print("init scroll") // Print("Setting scroll offset in introspect", setScrollOffset)
// thisScrollView = scrollView DispatchQueue.main.async {
// scrollView.contentOffset.y = CGFloat(selectedRibbon[0].scrollOffset) 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 introspect")
}
.listStyle(PlainListStyle())
}
.zIndex(1)
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
.frame(width: geometry.size.width - 50, height: geometry.size.height / 2 - vertSep)
.offset(x:30 , y:0)
.offset(x: pulledOut.width)
.offset(x: viewState.width, y: viewState.height)
.gesture(
DragGesture()
.onChanged { gesture in
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
if (gesture.translation.width < -50 && pulledOut.width == CGFloat(0)) {
dragOffset = gesture.translation.width + 50
}
}
//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
dragOffset = .zero
}
}
)
Text("DRAG")
.gesture(
DragGesture()
.onChanged { gesture in
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
// }
// } // }
)
Print("end instrospect") ScrollViewReader { proxy 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)")
// .onChange(of: geometry.frame(in: .named("scrollView"))) { imageRect in
//Print(imageRect)
//Print(outerProxy)
// if isInView(innerRect: imageRect, isIn: outerProxy) {
// visibleIndex.insert(item)
// } else {
// visibleIndex.remove(item)
// }
// }
}
}
.background(Color(red: 0.18, green: 0.18, blue: 0.18))
}
.onAppear() {
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)
}
//.onChange(of: refresh) { target in
// //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!
// // }
// }
// }
// }
//}
//.introspectScrollView { scrollView in
// Print("introspect")
// // scrollView.delegate = scrollDelegate
// //Print("Scroll delegate offset", scrollDelegate.scrollOffset)
// if (setScrollOffset != nil) {
// // Print("Setting scroll offset in introspect", setScrollOffset)
// DispatchQueue.main.async {
// 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")
//}
.listStyle(PlainListStyle())
} }
.listStyle(PlainListStyle()) .zIndex(1)
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
.frame(width: geometry.size.width - 50)
.offset(x:30 , y:0)
.offset(x: pulledOut.width)
.offset(x: viewState.width, y: viewState.height)
.gesture(
DragGesture()
.onChanged { gesture in
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
}
}
)
} }
.zIndex(1)
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
.frame(width: geometry.size.width - 50)
.offset(x:30 , y:0)
.offset(x: pulledOut.width)
.offset(x: viewState.width, y: viewState.height)
.gesture(
DragGesture()
.onChanged { gesture in
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
}
}
)
if (showOverlay) { if (showOverlay) {
Rectangle() Rectangle()
@ -609,6 +837,9 @@ struct ContentView: View {
} }
} }
func handleVisibilityChanged2(_ id: String, change: VisibilityChange, tracker: VisibilityTracker<String>) {
}
func handleVisibilityChanged(_ id: String, change: VisibilityChange, tracker: VisibilityTracker<String>) { func handleVisibilityChanged(_ id: String, change: VisibilityChange, tracker: VisibilityTracker<String>) {

View File

@ -40,7 +40,7 @@ extension AppDatabase {
// // demo purpose. // // demo purpose.
// try appDatabase.createRandomPlayersIfEmpty() // try appDatabase.createRandomPlayersIfEmpty()
// } // }
try appDatabase.createRandomLinesIfEmpty() try appDatabase.initDatabase()
return appDatabase return appDatabase
@ -69,7 +69,7 @@ extension AppDatabase {
/// Creates a database full of random players for SwiftUI previews /// Creates a database full of random players for SwiftUI previews
static func random() -> AppDatabase { static func random() -> AppDatabase {
let appDatabase = empty() let appDatabase = empty()
try! appDatabase.createRandomLinesIfEmpty() try! appDatabase.initDatabase()
return appDatabase return appDatabase
} }
} }

View File

@ -17,6 +17,7 @@ struct Ribbon: Identifiable, Equatable {
/// Int64 is the recommended type for auto-incremented database ids. /// Int64 is the recommended type for auto-incremented database ids.
/// Use nil for players that are not inserted yet in the database. /// Use nil for players that are not inserted yet in the database.
var id: Int64? var id: Int64?
var title: String
var book: String var book: String
var scrollId: String var scrollId: String
var scrollOffset: Int var scrollOffset: Int
@ -35,6 +36,7 @@ extension Ribbon: Codable, FetchableRecord, MutablePersistableRecord {
fileprivate enum Columns { fileprivate enum Columns {
static let id = Column(CodingKeys.id) static let id = Column(CodingKeys.id)
static let book = Column(CodingKeys.book) static let book = Column(CodingKeys.book)
static let title = Column(CodingKeys.title)
static let scrollOffset = Column(CodingKeys.scrollOffset) static let scrollOffset = Column(CodingKeys.scrollOffset)
} }

22
test
View File

@ -1,22 +0,0 @@
struct ContentView: View {
@State var scrollId : String?
var body: some View {
SwitchButton(scrollId:$scrollId)
}
}
struct SwitchButton : View {
@Binding var scrollId : String?
var body: some View {
Button("This button",
action: {
goToRibbon($scrollId)
}
)
}
}
func goToRibbon(scrollId: Binding<String?>) {
scrollId = "SomeValue"
}

3
test.c
View File

@ -1,3 +0,0 @@
int main() {
return 0;
}