2023-02-27 14:27:15 -08:00
|
|
|
//
|
|
|
|
// ContentView.swift
|
|
|
|
// gloss
|
|
|
|
//
|
|
|
|
// Created by Saint on 10/23/22.
|
|
|
|
//
|
|
|
|
|
|
|
|
import SwiftUI
|
|
|
|
import GRDB
|
|
|
|
import GRDBQuery
|
|
|
|
import Introspect
|
|
|
|
import os
|
|
|
|
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "network")
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-27 14:27:15 -08:00
|
|
|
extension UINavigationController {
|
|
|
|
override open func viewDidLoad() {
|
|
|
|
super.viewDidLoad()
|
|
|
|
|
|
|
|
let standard = UINavigationBarAppearance()
|
|
|
|
standard.backgroundColor = .red //When you scroll or you have title (small one)
|
|
|
|
|
|
|
|
let compact = UINavigationBarAppearance()
|
|
|
|
compact.backgroundColor = .green //compact-height
|
|
|
|
|
|
|
|
let scrollEdge = UINavigationBarAppearance()
|
|
|
|
scrollEdge.backgroundColor = .blue //When you have large title
|
|
|
|
|
|
|
|
navigationBar.standardAppearance = standard
|
|
|
|
navigationBar.compactAppearance = compact
|
|
|
|
navigationBar.scrollEdgeAppearance = scrollEdge
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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-02-28 14:03:58 -08:00
|
|
|
struct PositionObservingView<Content: View>: View {
|
|
|
|
var coordinateSpace: CoordinateSpace
|
|
|
|
@Binding var position: CGPoint
|
|
|
|
@ViewBuilder var content: () -> Content
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
content()
|
|
|
|
.background(GeometryReader { geometry in
|
|
|
|
Color.clear.preference(
|
|
|
|
key: PreferenceKey.self,
|
|
|
|
value: geometry.frame(in: coordinateSpace).origin
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.onPreferenceChange(PreferenceKey.self) { position in
|
|
|
|
self.position = position
|
|
|
|
// Print(self.position)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private extension PositionObservingView {
|
|
|
|
struct PreferenceKey: SwiftUI.PreferenceKey {
|
|
|
|
static var defaultValue: CGPoint { .zero }
|
|
|
|
|
|
|
|
static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
|
|
|
|
// No-op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct OffsetObservingScrollView<Content: View>: View {
|
|
|
|
var axes: Axis.Set = [.vertical]
|
|
|
|
var showsIndicators = true
|
|
|
|
@Binding var offset: CGPoint
|
|
|
|
@ViewBuilder var content: () -> Content
|
|
|
|
|
|
|
|
// The name of our coordinate space doesn't have to be
|
|
|
|
// stable between view updates (it just needs to be
|
|
|
|
// consistent within this view), so we'll simply use a
|
|
|
|
// plain UUID for it:
|
|
|
|
private let coordinateSpaceName = UUID()
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
ScrollView(axes, showsIndicators: showsIndicators) {
|
|
|
|
PositionObservingView(
|
|
|
|
coordinateSpace: .named(coordinateSpaceName),
|
|
|
|
position: Binding(
|
|
|
|
get: { offset },
|
|
|
|
set: { newOffset in
|
|
|
|
offset = CGPoint(
|
|
|
|
x: -newOffset.x,
|
|
|
|
y: -newOffset.y
|
|
|
|
)
|
|
|
|
}
|
|
|
|
),
|
|
|
|
content: content
|
|
|
|
)
|
|
|
|
}
|
|
|
|
.coordinateSpace(name: coordinateSpaceName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-27 14:27:15 -08:00
|
|
|
|
|
|
|
struct SwitchButton : View {
|
2023-02-28 14:03:58 -08:00
|
|
|
@State var ribbon: Ribbon
|
|
|
|
// @State var selectedRibbon: SelectedRibbon
|
2023-02-27 14:27:15 -08:00
|
|
|
@Binding var book : String
|
|
|
|
@Binding var scrollOffset : CGFloat
|
2023-02-28 14:03:58 -08:00
|
|
|
@Binding var readOffset: CGPoint
|
|
|
|
|
|
|
|
@Environment(\.appDatabase) private var appDatabase
|
2023-02-27 14:27:15 -08:00
|
|
|
|
2023-02-28 14:03:58 -08:00
|
|
|
|
|
|
|
@Query(SelectedRibbonRequest()) private var sr: [SelectedRibbon]
|
|
|
|
|
|
|
|
@State var saveOffset = CGFloat()
|
2023-02-27 14:27:15 -08:00
|
|
|
var body: some View {
|
2023-02-28 14:03:58 -08:00
|
|
|
// ForEach(sr) { selectedRibbon in
|
|
|
|
Button("meow",
|
|
|
|
action: {
|
|
|
|
Task {
|
|
|
|
var selectedRibbon = sr[0]
|
|
|
|
|
|
|
|
saveOffset = CGFloat(readOffset.y)
|
|
|
|
Print("save/read offset", readOffset.y)
|
|
|
|
|
|
|
|
Print("START")
|
|
|
|
_ = Print(ribbon)
|
|
|
|
_ = Print(selectedRibbon)
|
|
|
|
Print("START2")
|
|
|
|
|
|
|
|
if (selectedRibbon.ribbonId != ribbon.id!) {
|
|
|
|
Print(ribbon.id!)
|
|
|
|
Print("switching")
|
|
|
|
book = ribbon.book
|
|
|
|
scrollOffset = CGFloat(ribbon.scrollOffset)
|
|
|
|
// scrollOffset = CGFloat(1500)
|
|
|
|
Print("setted offset value", scrollOffset)
|
|
|
|
selectedRibbon.ribbonId = ribbon.id!
|
|
|
|
_ = try await appDatabase.saveSelectedRibbon(&selectedRibbon)
|
|
|
|
_ = Print(selectedRibbon)
|
|
|
|
}
|
|
|
|
var editedRibbon = ribbon
|
|
|
|
editedRibbon.scrollOffset = Int(saveOffset)
|
|
|
|
Print("current ribbon offset after potential switch", editedRibbon.scrollOffset)
|
|
|
|
|
|
|
|
_ = try await appDatabase.saveRibbon(&editedRibbon)
|
|
|
|
_ = Print(editedRibbon)
|
|
|
|
|
|
|
|
Print("ribbon offset saved")
|
|
|
|
|
|
|
|
Print("set offset value", scrollOffset)
|
|
|
|
Print("read offset value", readOffset.y)
|
|
|
|
|
|
|
|
|
|
|
|
Print("END")
|
|
|
|
_ = Print(ribbon)
|
|
|
|
_ = Print(selectedRibbon)
|
|
|
|
Print("END2")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
)
|
|
|
|
.buttonStyle(BlueButtonStyle())
|
|
|
|
// }
|
2023-02-27 14:27:15 -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 scrollTo1 : Int64?
|
|
|
|
@State var selectedLine : Int64?
|
|
|
|
@State var scrollOffset = CGFloat()
|
2023-02-28 14:03:58 -08:00
|
|
|
|
|
|
|
// @State var selectedRibbon: Ribbon!,
|
|
|
|
// @State var selectedRibbon: Ribbon!
|
|
|
|
|
|
|
|
// @State var selectedRibbonId = Int64(UserDefaults.standard.optionalInt(forKey: "selectedRibbonId") ?? 1)
|
|
|
|
|
|
|
|
|
|
|
|
@Query(SelectedRibbonRequest()) private var selectedRibbon: [SelectedRibbon]
|
|
|
|
|
|
|
|
@State var endedDrag = true
|
|
|
|
|
|
|
|
@State var readOffset = CGPoint()
|
2023-02-27 14:27:15 -08:00
|
|
|
|
|
|
|
@Query(LineRequest(ordering: .byScore, book: "bible.john")) private var lines: [Line]
|
2023-02-28 14:03:58 -08:00
|
|
|
|
2023-02-27 14:27:15 -08:00
|
|
|
|
|
|
|
@Query(RibbonRequest()) private var ribbons: [Ribbon]
|
|
|
|
|
2023-02-28 14:03:58 -08:00
|
|
|
// @Query*RibbonRequest> private var selectedRibbon: [Ribbon]
|
|
|
|
|
|
|
|
// @Query(RibbonRequest(id: Int64(UserDefaults.standard.optionalInt(forKey: "lastRibbonId") ?? 1))) private var selectedRibbon: [Ribbon]
|
2023-02-27 14:27:15 -08:00
|
|
|
|
|
|
|
init() {
|
|
|
|
UITableView.appearance().backgroundColor = UIColor(Color(red: 0.2, green: 0.2, blue: 0.2))
|
2023-02-28 14:03:58 -08:00
|
|
|
// _selectedRibbon = Query(RibbonRequest(id: Int64(UserDefaults.standard.optionalInt(forKey: "lastRibbonId") ?? 1)))
|
2023-02-27 14:27:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
GeometryReader { geometry in
|
|
|
|
ZStack{
|
|
|
|
VStack{
|
2023-02-28 14:03:58 -08:00
|
|
|
ForEach(ribbons) { ribbon in
|
|
|
|
ForEach(selectedRibbon) { sr in
|
|
|
|
SwitchButton(ribbon: ribbon,
|
|
|
|
// selectedRibbon:sr,
|
|
|
|
book: $lines.book,
|
|
|
|
scrollOffset: $scrollOffset,
|
|
|
|
readOffset: $readOffset
|
|
|
|
)
|
|
|
|
.buttonStyle(BlueButtonStyle())
|
|
|
|
}
|
2023-02-27 14:27:15 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
|
|
|
|
.background(Color.red)
|
|
|
|
|
|
|
|
// VStack (spacing: 0){
|
|
|
|
ScrollViewReader { proxy in
|
|
|
|
//ScrollableView($offset, animationDuration: 0) {
|
2023-02-28 14:03:58 -08:00
|
|
|
OffsetObservingScrollView(offset: $readOffset)
|
|
|
|
{
|
2023-02-27 14:27:15 -08:00
|
|
|
// List {
|
|
|
|
LazyVStack {
|
|
|
|
ForEach(lines) { line in
|
|
|
|
Text(String(line.body))
|
|
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
|
|
.contentShape(Rectangle())
|
|
|
|
.font(Font.custom("AveriaSerifLibre-Regular", size: 30))
|
|
|
|
.listRowBackground(Color(red: 0.2, green: 0.8, blue: 0.2))
|
|
|
|
.foregroundColor(Color.white)
|
|
|
|
.listRowInsets(EdgeInsets())
|
|
|
|
.padding(EdgeInsets(top: 10, leading: 20, bottom: 40, trailing: 20))
|
|
|
|
.listRowSeparator(.hidden)
|
|
|
|
.id(line.id!)
|
|
|
|
.onTapGesture {
|
|
|
|
selectedLine = line.id!
|
|
|
|
//Print(selectedLine)
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
|
|
|
|
//.onChange(of: scrollTo1) { scrollTo in
|
|
|
|
// // scrollTo1 = 0
|
|
|
|
// let target = scrollTo
|
|
|
|
// //Print("hellosdf")
|
|
|
|
// //Print("value:", target)
|
|
|
|
// //Print("value2:", scrollTo)
|
|
|
|
// proxy.scrollTo(target, anchor: .top)
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
.introspectScrollView { scrollView in
|
|
|
|
//let width = scrollView.contentSize.width - scrollView.frame.width
|
|
|
|
//Print(scrollView.contentOffset.x)
|
2023-02-28 14:03:58 -08:00
|
|
|
// Print("here")
|
|
|
|
if (scrollOffset != scrollView.contentOffset.y) {
|
|
|
|
scrollView.contentOffset.y = scrollOffset
|
|
|
|
}
|
2023-02-27 14:27:15 -08:00
|
|
|
}
|
|
|
|
.listStyle(PlainListStyle())
|
|
|
|
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
.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-27 14:27:15 -08:00
|
|
|
// logger.error("hello222")
|
|
|
|
// NSLog("hellooo")
|
|
|
|
//Print(viewState.width)
|
|
|
|
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
|
2023-02-27 14:27:15 -08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private struct LineRow: View {
|
|
|
|
var line: Line
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
HStack {
|
|
|
|
|
|
|
|
//Print("Here I am", line.body)
|
|
|
|
Text(line.body)
|
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|