gloss-ios/gloss/ContentView.swift

608 lines
23 KiB
Swift
Raw Normal View History

//
// ContentView.swift
// gloss
//
// Created by Saint on 10/23/22.
//
import SwiftUI
import GRDB
import GRDBQuery
import Introspect
import os
2023-03-11 20:31:48 -08:00
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "network")
2023-04-23 20:41:17 -07:00
var currentId : String?
var currentOffset : CGFloat?
var gTracker: VisibilityTracker<String>?
2023-06-01 12:45:36 -07:00
var printCount: Int64 = 0
2023-04-23 20:41:17 -07:00
// var curBook = "John"
2023-02-28 14:03:58 -08:00
extension UserDefaults {
public func optionalInt(forKey defaultName: String) -> Int? {
let defaults = self
if let value = defaults.value(forKey: defaultName) {
return value as? Int
}
return nil
}
public func optionalBool(forKey defaultName: String) -> Bool? {
let defaults = self
if let value = defaults.value(forKey: defaultName) {
return value as? Bool
}
return nil
}
}
struct BlueButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.font(.headline)
.frame(width: 160)
.contentShape(Rectangle())
.foregroundColor(configuration.isPressed ? Color.white.opacity(0.5) : Color.black)
.background(configuration.isPressed ? Color.purple.opacity(0.5) : Color.purple)
.listRowBackground(configuration.isPressed ? Color.blue.opacity(0.5) : Color.black)
}
}
2023-05-31 13:57:17 -07:00
func goToRibbon(selectedRibbon: Ribbon,
destRibbon: Ribbon,
scrollId: Binding<String?>,
scrollOffset: Binding<CGFloat?>,
refresh: Binding<Bool>,
2023-06-01 12:45:36 -07:00
appDatabase: AppDatabase,
loading: Bool
)
{
2023-05-31 13:57:17 -07:00
2023-06-01 12:45:36 -07:00
Task {
// print("SELECTED RIBBON", selectedRibbon)
2023-05-31 13:57:17 -07:00
var scrollOffsetToSave = currentOffset
var scrollIdToSave = currentId
var updatedRibbon = selectedRibbon
2023-06-01 12:45:36 -07:00
if (selectedRibbon.id != destRibbon.id! || loading) {
print("switching ribbons")
2023-05-31 13:57:17 -07:00
2023-06-01 12:45:36 -07:00
if (loading) {
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)
} catch {
// Print("something wrong")
}
}
2023-06-01 12:45:36 -07:00
if (!loading) {
print("not loading")
updatedRibbon.scrollOffset = Int(scrollOffsetToSave!)
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
}
}
struct SwitchButton : View {
2023-03-01 10:47:34 -08:00
var ribbon: Ribbon
@Binding var scrollId : String?
@Binding var scrollOffset : CGFloat?
@Binding var refresh : Bool
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
2023-05-31 13:57:17 -07:00
2023-02-28 14:03:58 -08:00
@State var saveOffset = CGFloat()
var body: some View {
2023-02-28 14:03:58 -08:00
// ForEach(sr) { selectedRibbon in
2023-05-31 13:57:17 -07:00
let ribbonString = String(sr[0].id!) + " " + String(ribbon.id!) + " " + String(ribbon.scrollOffset) + " " + ribbon.scrollId
Button(ribbonString,
2023-03-01 10:47:34 -08:00
action: {
Task {
2023-05-31 13:57:17 -07:00
goToRibbon(selectedRibbon: sr[0],
destRibbon: ribbon,
scrollId: $scrollId,
scrollOffset: $scrollOffset,
refresh: $refresh,
2023-06-01 12:45:36 -07:00
appDatabase: appDatabase,
loading: false)
2023-03-01 10:47:34 -08:00
}
}
)
.buttonStyle(BlueButtonStyle())
}
// }
}
2023-02-28 14:03:58 -08:00
2023-04-21 17:06:30 -07:00
// class ScrollViewHandler: NSObject {
// public var scrollOffset = CGFloat(10)
// }
2023-02-28 14:03:58 -08:00
2023-04-21 17:06:30 -07:00
// extension ScrollViewHandler: UIScrollViewDelegate {
// func scrollViewDidScroll(_ scrollView: UIScrollView) {
// scrollOffset = CGFloat(scrollView.contentOffset.y)
// // print("delegate", scrollView.contentOffset.y)
// // print("delegate prop", self.scrollOffset)
// }
// }
2023-03-01 10:47:34 -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()
segSplit.enumerated().forEach({ (index, item) in
let verse = try! decoder.decode(Verse.self, from: item.data(using: .utf8)!)
retView = retView + Text(String(verse.verse))
2023-04-23 20:41:17 -07:00
.font(Font.custom("AveriaSerifLibre-Regular", size: 6))
2023-03-11 20:31:48 -08:00
.baselineOffset(6.0)
.foregroundColor(Color.white)
retView = retView + Text(verse.body)
.foregroundColor(Color.white)
2023-04-23 20:41:17 -07:00
.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
2023-03-01 10:47:34 -08:00
2023-03-11 20:31:48 -08:00
var body: some View {
// makeVerseView(seg: seg)
var retView = Text("")
var segSplit = seg.body.components(separatedBy: ";;")
let decoder = JSONDecoder()
// Text(segSplit[0].body)
// .id(seg.id)
// VStack {
// ForEach(segSplit.indices) { i in
segSplit.enumerated().forEach({ (index, item) in
let verse = try! decoder.decode(Verse.self, from: item.data(using: .utf8)!)
2023-05-31 13:57:17 -07:00
var attributedString: AttributedString {
// var result = AttributedString("Hello World!")
var result = AttributedString(verse.body)
result.underlineStyle = Text.LineStyle(
pattern: .dot, color: .white)
return result
}
2023-06-01 12:45:36 -07:00
retView = retView + Text(String(verse.verse)) + Text(String(ribbonId))
2023-05-31 13:57:17 -07:00
//retView = retView + Text(attributedString)
2023-03-11 20:31:48 -08:00
// Text(seg.body)
// .contentShape(Rectangle())
2023-04-23 20:41:17 -07:00
.font(Font.custom("AveriaSerifLibre-Regular", size: 10))
2023-03-11 20:31:48 -08:00
.baselineOffset(6.0)
2023-05-31 13:57:17 -07:00
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
2023-03-11 20:31:48 -08:00
2023-05-31 13:57:17 -07:00
retView = retView + Text(attributedString)
2023-03-11 20:31:48 -08:00
// .frame(maxWidth: .infinity, alignment: .leading)
// .contentShape(Rectangle())
2023-05-31 13:57:17 -07:00
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
2023-04-23 20:41:17 -07:00
.font(Font.custom("AveriaSerifLibre-Regular", size: 20))
2023-03-11 20:31:48 -08:00
// .listRowBackground(Color(red: 0.2, green: 0.8, blue: 0.2))
// .listRowInsets(EdgeInsets())
// .padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20))
// .listRowSeparator(.hidden)
// .id(String(seg.id) + "body" + String(i))
// .id(seg.id)
//.onTapGesture {
// selectedLine = seg.id
//Print(selectedLine)
2023-03-11 20:31:48 -08:00
//}
// .listRowBackground(Color(red: 0.2, green: 0.8, blue: 0.2))
// .listRowInsets(EdgeInsets())
// .padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20))
// .listRowSeparator(.hidden)
// .id(String(seg.id) + "verse" + String(i))
// .id(seg.id)
//.onTapGesture {
// selectedLine = seg.id
//Print(selectedLine)
2023-03-11 20:31:48 -08:00
//}
})
// }
return retView
}
}
2023-03-01 10:47:34 -08:00
struct ContentView: View {
@State var viewState = CGSize.zero
@State var pulledOut = CGSize.zero
@State var taskTitle : String = "FIRST DOGGG"
@State var curBook : String = "Matthew"
@State var selectedLine : Int64?
2023-02-28 14:03:58 -08:00
2023-03-01 10:47:34 -08: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-23 20:41:17 -07:00
// @State var currentId : String?
// @State var currentOffset = CGFloat()
2023-04-21 17:06:30 -07:00
// set this to scroll to area
@State var scrollId : String?
@State var scrollOffset: CGFloat?
@State var setScrollOffset: CGFloat?
2023-04-21 17:06:30 -07:00
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-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
@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-06-01 12:45:36 -07:00
init() {
UITableView.appearance().backgroundColor = UIColor(Color(red: 0.2, green: 0.2, blue: 0.2))
2023-06-01 12:45:36 -07:00
_selectedRibbon = Query(SelectedRibbonRequest())
2023-04-21 17:06:30 -07:00
// self._scrollDelegate = State(initialValue: ScrollViewHandler())
}
var body: some View {
// Print("rendering")
2023-03-11 20:31:48 -08:00
2023-05-31 13:57:17 -07:00
var size1 = CGFloat(70)
var size2 = CGFloat(120)
var fontSize = CGFloat(20)
GeometryReader { geometry in
2023-06-01 12:45:36 -07:00
ZStack {
VStack{
2023-05-31 13:57:17 -07:00
Text("MK")
.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))
2023-05-31 13:57:17 -07:00
.overlay( MyCustomShape().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("Ps")
.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( MyCustomShape().frame(width: size1, height: size1) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))))
// .foregroundColor(.white))
.frame(width: size1, height: size1)
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( MyCustomShape().frame(width: size1, height: size1) .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))))
// .foregroundColor(.white))
.frame(width: size1, height: size1)
2023-03-11 20:31:48 -08:00
// Text("MTW")
// .font(Font.custom("AveriaSerifLibre-Regular", size: 20))
// .foregroundColor(Color.white)
// .overlay( MyCustomShape().frame(width: 120, height: 100))
// .frame(width: 120, height: 120)
2023-03-11 20:31:48 -08:00
2023-02-28 14:03:58 -08:00
ForEach(ribbons) { ribbon in
SwitchButton(ribbon: ribbon,
scrollId:$scrollId,
scrollOffset:$scrollOffset,
refresh:$refresh
)
.buttonStyle(BlueButtonStyle())
// Print("RIBBON")
// Print(ribbon)
}
}
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
2023-03-11 20:31:48 -08:00
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
ScrollViewReader { proxy in
VisibilityTrackingScrollView(action: handleVisibilityChanged) {
// ScrollView {
LazyVStack {
2023-03-11 20:31:48 -08:00
Text(refresh ? "Selected" : "not Selected")
Button("Jump to #8") {
2023-04-21 17:06:30 -07:00
scrollId = "20"
2023-03-11 20:31:48 -08:00
}
ForEach(segs) { seg in
2023-06-01 12:45:36 -07:00
SegRow(seg: seg,
ribbonId: selectedRibbon[0].id!
)
2023-03-11 20:31:48 -08:00
.id("\(seg.id)")
.padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20))
2023-03-11 20:31:48 -08:00
.trackVisibility(id: "\(seg.id)")
// .onChange(of: geometry.frame(in: .named("scrollView"))) { imageRect in
//Print(imageRect)
//Print(outerProxy)
2023-03-11 20:31:48 -08:00
// if isInView(innerRect: imageRect, isIn: outerProxy) {
// visibleIndex.insert(item)
// } else {
// visibleIndex.remove(item)
// }
// }
}
}
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
}
2023-06-01 12:45:36 -07:00
.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,
appDatabase: appDatabase,
loading: true)
}
2023-06-02 14:25:20 -07:00
.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 {
2023-06-02 16:20:04 -07:00
Print("scroll Id target: \(scrollId)")
2023-06-02 14:25:20 -07:00
proxy.scrollTo(scrollId! , anchor: .top)
// proxy.scrollTo(String(Int(scrollId!)! + 1))
// currentId = scrollId!
// if (currentId != scrollId!) {
2023-06-02 16:20:04 -07:00
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
2023-06-02 14:25:20 -07:00
2023-06-02 16:20:04 -07:00
Print(" scroll id target", scrollId)
Print(" current id ", currentId)
Print(gTracker!.sortedViewIDs)
2023-06-02 14:25:20 -07:00
if (currentId! != scrollId!) {
Print("NO MATCH")
}
2023-06-02 14:25:20 -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!))
2023-06-02 16:20:04 -07:00
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()
}
2023-06-02 14:25:20 -07:00
// // currentId = scrollId!
// DispatchQueue.main.async {
// currentOffset = scrollOffset!
// currentId = scrollId!
// }
}
2023-04-21 17:06:30 -07:00
}
2023-06-02 14:25:20 -07:00
}
}
.introspectScrollView { scrollView in
Print("introspect")
// scrollView.delegate = scrollDelegate
//Print("Scroll delegate offset", scrollDelegate.scrollOffset)
if (setScrollOffset != nil) {
// Print("Setting scroll offset in introspect", setScrollOffset)
scrollView.contentOffset.y = scrollView.contentOffset.y + setScrollOffset!
DispatchQueue.main.async { setScrollOffset = nil }
}
// if (thisScrollView == nil) {
// Print("init scroll")
// thisScrollView = scrollView
// scrollView.contentOffset.y = CGFloat(selectedRibbon[0].scrollOffset)
// }
Print("end instrospect")
}
.listStyle(PlainListStyle())
2023-03-11 20:31:48 -08:00
}
.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
2023-02-28 14:03:58 -08:00
if (endedDrag) {
endedDrag = false
scrollOffset = readOffset.y - 20
// _ = Print("meow")
2023-02-28 14:03:58 -08:00
}
// logger.error("hello222")
// NSLog("hellooo")
Print(viewState.width)
2023-03-11 20:31:48 -08:00
if (abs(gesture.translation.width) > 20) {
viewState.width = gesture.translation.width
}
//offset.y = gesture.translation.width
// logger.log("hello")
}
.onEnded { _ in
2023-02-28 14:03:58 -08:00
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
}
}
)
}
}
}
2023-03-11 20:31:48 -08:00
func handleVisibilityChanged(_ id: String, change: VisibilityChange, tracker: VisibilityTracker<String>) {
2023-04-21 17:06:30 -07:00
2023-04-23 20:41:17 -07:00
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-04-21 17:06:30 -07:00
// if (currentId != nil) {
// currentOffset = tracker.visibleViews[currentId!]!
// }
2023-04-23 20:41:17 -07:00
let visibleViews2 = Array(tracker.visibleViews.keys)
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!]!
// }
// }
2023-06-02 14:25:20 -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
}()
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
ContentView().environment(\.appDatabase, .random())
}
}
extension View {
func Print(_ vars: Any...) -> some View {
for v in vars { print(v) }
return EmptyView()
}
}