Compare commits
No commits in common. "bd1923cfb413610724d41dfc56eb08400dd546ca" and "ae49a5cbfe8439d83dbd216149be926833efda6a" have entirely different histories.
bd1923cfb4
...
ae49a5cbfe
|
@ -1,55 +0,0 @@
|
||||||
//
|
|
||||||
// BackButton.swift
|
|
||||||
// gloss
|
|
||||||
//
|
|
||||||
// Created by Saint on 5/27/24.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
struct BackArrow: Shape {
|
|
||||||
func path(in rect: CGRect) -> Path {
|
|
||||||
var path = Path()
|
|
||||||
let width = rect.size.width
|
|
||||||
let height = rect.size.height
|
|
||||||
path.move(to: CGPoint(x: 0.83333*width, y: 0.45833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.83333*width, y: 0.54167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.33333*width, y: 0.54167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.33333*width, y: 0.625*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.25*width, y: 0.625*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.25*width, y: 0.54167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.16667*width, y: 0.54167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.16667*width, y: 0.45833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.25*width, y: 0.45833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.25*width, y: 0.375*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.33333*width, y: 0.375*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.33333*width, y: 0.45833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.83333*width, y: 0.45833*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
path.move(to: CGPoint(x: 0.41667*width, y: 0.29167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.33333*width, y: 0.29167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.33333*width, y: 0.375*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.41667*width, y: 0.375*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.41667*width, y: 0.29167*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
path.move(to: CGPoint(x: 0.41667*width, y: 0.29167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.5*width, y: 0.29167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.5*width, y: 0.20833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.41667*width, y: 0.20833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.41667*width, y: 0.29167*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
path.move(to: CGPoint(x: 0.41667*width, y: 0.70833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.33333*width, y: 0.70833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.33333*width, y: 0.625*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.41667*width, y: 0.625*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.41667*width, y: 0.70833*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
path.move(to: CGPoint(x: 0.41667*width, y: 0.70833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.5*width, y: 0.70833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.5*width, y: 0.79167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.41667*width, y: 0.79167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.41667*width, y: 0.70833*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,8 +5,6 @@
|
||||||
// Created by Saint on 5/20/24.
|
// Created by Saint on 5/20/24.
|
||||||
//
|
//
|
||||||
|
|
||||||
import GRDB
|
|
||||||
import GRDBQuery
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import WrappingHStack
|
import WrappingHStack
|
||||||
|
@ -16,7 +14,6 @@ struct SegRow: View {
|
||||||
var ribbonId: Int64
|
var ribbonId: Int64
|
||||||
@State var highlights = Set<Int>()
|
@State var highlights = Set<Int>()
|
||||||
|
|
||||||
let intraWordSpacing = CGFloat(1.6)
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
var segSplit = seg.body.components(separatedBy: ";;")
|
var segSplit = seg.body.components(separatedBy: ";;")
|
||||||
let decoder = JSONDecoder()
|
let decoder = JSONDecoder()
|
||||||
|
@ -56,8 +53,7 @@ struct SegRow: View {
|
||||||
Text(arrayOfText[index])
|
Text(arrayOfText[index])
|
||||||
.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)))
|
||||||
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
||||||
|
.padding(.horizontal, 1.5) // intra word spacing
|
||||||
.padding(.horizontal, intraWordSpacing) // intra word spacing
|
|
||||||
.if(self.highlights.contains(verse.verse)) { $0.background(Color(hex: highlightColor)) }
|
.if(self.highlights.contains(verse.verse)) { $0.background(Color(hex: highlightColor)) }
|
||||||
.foregroundColor(Color.white)
|
.foregroundColor(Color.white)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
@ -83,6 +79,7 @@ struct SegRow: View {
|
||||||
struct Pane: View {
|
struct Pane: View {
|
||||||
@ObservedObject var paneConnector: PaneConnector
|
@ObservedObject var paneConnector: PaneConnector
|
||||||
|
|
||||||
|
@State var segs: [SegDenorm]
|
||||||
@State var selectedRibbon: [Ribbon]
|
@State var selectedRibbon: [Ribbon]
|
||||||
|
|
||||||
@State var width: CGFloat
|
@State var width: CGFloat
|
||||||
|
@ -92,15 +89,13 @@ struct Pane: View {
|
||||||
|
|
||||||
@State var refresh: Bool = false
|
@State var refresh: Bool = false
|
||||||
|
|
||||||
@Query(SegDenormRequest(book: "bible.mark")) private var segs: [SegDenorm]
|
@State var vertSep = CGFloat(20)
|
||||||
|
|
||||||
@Environment(\.appDatabase) private var appDatabase
|
@Environment(\.appDatabase) private var appDatabase
|
||||||
|
|
||||||
// var handleVisibilityChanged: (String, VisibilityChange, VisibilityTracker<String>) -> Void
|
// var handleVisibilityChanged: (String, VisibilityChange, VisibilityTracker<String>) -> Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View{
|
||||||
var adjustedHeight = height - paneConnector.vertSep
|
|
||||||
ZStack {
|
|
||||||
ScrollViewReader { proxy in
|
ScrollViewReader { proxy in
|
||||||
VisibilityTrackingScrollView(action: handleVisibilityChanged) {
|
VisibilityTrackingScrollView(action: handleVisibilityChanged) {
|
||||||
LazyVStack {
|
LazyVStack {
|
||||||
|
@ -121,8 +116,8 @@ struct Pane: View {
|
||||||
destRibbon: selectedRibbon[0],
|
destRibbon: selectedRibbon[0],
|
||||||
appDatabase: appDatabase,
|
appDatabase: appDatabase,
|
||||||
paneConnector: paneConnector,
|
paneConnector: paneConnector,
|
||||||
loading: true,
|
refresh: $refresh,
|
||||||
bump: false)
|
loading: true)
|
||||||
}
|
}
|
||||||
.onChange(of: paneConnector.refresh) { _ in
|
.onChange(of: paneConnector.refresh) { _ in
|
||||||
print("inside change")
|
print("inside change")
|
||||||
|
@ -130,9 +125,6 @@ struct Pane: View {
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
if paneConnector.visibilityTracker == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let gTracker = paneConnector.visibilityTracker!
|
let gTracker = paneConnector.visibilityTracker!
|
||||||
|
|
||||||
Print("scroll Id target: \(paneConnector.scrollId)")
|
Print("scroll Id target: \(paneConnector.scrollId)")
|
||||||
|
@ -198,28 +190,8 @@ struct Pane: View {
|
||||||
}
|
}
|
||||||
.zIndex(1)
|
.zIndex(1)
|
||||||
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
|
.background(Color(red: 0.2, green: 0.2, blue: 0.2))
|
||||||
.frame(width: width, height: adjustedHeight)
|
.frame(width: width, height: height)
|
||||||
|
|
||||||
if self.paneConnector.showOverlay {
|
|
||||||
Rectangle()
|
|
||||||
// .frame(width: width, height: height + 200)
|
|
||||||
.background(.ultraThinMaterial)
|
|
||||||
.opacity(0.98)
|
|
||||||
.offset(y: -50)
|
|
||||||
.frame(width: width, height: adjustedHeight + 100)
|
|
||||||
|
|
||||||
// .blur(radius: 0.8)
|
|
||||||
// .opacity(1)
|
|
||||||
.transition(.opacity)
|
|
||||||
|
|
||||||
// .frame(width: geometry.size.width - 50)
|
|
||||||
// .offset(x: pulledOut.width)
|
|
||||||
// .offset(x: viewState.width, y: viewState.height)
|
|
||||||
.zIndex(2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.frame(width: width, height: adjustedHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleVisibilityChanged(_: String, change _: VisibilityChange, tracker: VisibilityTracker<String>) {
|
func handleVisibilityChanged(_: String, change _: VisibilityChange, tracker: VisibilityTracker<String>) {
|
||||||
// var printRate: Int64 = 10
|
// var printRate: Int64 = 10
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
//
|
|
||||||
// ForwardArrow.swift
|
|
||||||
// gloss
|
|
||||||
//
|
|
||||||
// Created by Saint on 5/27/24.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct ForwardArrow: Shape {
|
|
||||||
func path(in rect: CGRect) -> Path {
|
|
||||||
var path = Path()
|
|
||||||
let width = rect.size.width
|
|
||||||
let height = rect.size.height
|
|
||||||
path.move(to: CGPoint(x: 0.16667*width, y: 0.45833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.16667*width, y: 0.54167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.66667*width, y: 0.54167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.66667*width, y: 0.625*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.75*width, y: 0.625*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.75*width, y: 0.54167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.83333*width, y: 0.54167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.83333*width, y: 0.45833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.75*width, y: 0.45833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.75*width, y: 0.375*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.66667*width, y: 0.375*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.66667*width, y: 0.45833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.16667*width, y: 0.45833*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
path.move(to: CGPoint(x: 0.58333*width, y: 0.29167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.66667*width, y: 0.29167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.66667*width, y: 0.375*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.58333*width, y: 0.375*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.58333*width, y: 0.29167*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
path.move(to: CGPoint(x: 0.58333*width, y: 0.29167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.5*width, y: 0.29167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.5*width, y: 0.20833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.58333*width, y: 0.20833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.58333*width, y: 0.29167*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
path.move(to: CGPoint(x: 0.58333*width, y: 0.70833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.66667*width, y: 0.70833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.66667*width, y: 0.625*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.58333*width, y: 0.625*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.58333*width, y: 0.70833*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
path.move(to: CGPoint(x: 0.58333*width, y: 0.70833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.5*width, y: 0.70833*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.5*width, y: 0.79167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.58333*width, y: 0.79167*height))
|
|
||||||
path.addLine(to: CGPoint(x: 0.58333*width, y: 0.70833*height))
|
|
||||||
path.closeSubpath()
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
|
|
||||||
import GRDB
|
|
||||||
import GRDBQuery
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct NaviBar: View {
|
|
||||||
@ObservedObject var paneConnector: PaneConnector
|
|
||||||
|
|
||||||
@Query(RibbonRequest(dir: .prev, groupId: 1)) private var backRibbon: [Ribbon]
|
|
||||||
@Query(RibbonRequest(dir: .next, groupId: 1)) private var nextRibbon: [Ribbon]
|
|
||||||
@Query(SelectedRibbonRequest()) private var selectedRibbon: [Ribbon]
|
|
||||||
@Environment(\.appDatabase) private var appDatabase
|
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
VStack {
|
|
||||||
HStack {
|
|
||||||
Print("meow navi reloaded back ribbon: \(backRibbon[0])")
|
|
||||||
|
|
||||||
BackArrow()
|
|
||||||
.frame(width: CGFloat(30), height: CGFloat(30))
|
|
||||||
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4)))
|
|
||||||
.onTapGesture {
|
|
||||||
print("back backRibbon: \(backRibbon)")
|
|
||||||
Task {
|
|
||||||
print("back backRibbon: \(backRibbon)")
|
|
||||||
if backRibbon.count == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var br = backRibbon[0]
|
|
||||||
//var sr = selectedRibbon[0]
|
|
||||||
|
|
||||||
do {
|
|
||||||
|
|
||||||
var sr = try await appDatabase.getSelectedRibbon()
|
|
||||||
print("meow first sr:\(sr)")
|
|
||||||
print("meow first selectedRibbon:\(selectedRibbon[0])")
|
|
||||||
try await updateRibbon(selectedRibbon: selectedRibbon[0],
|
|
||||||
appDatabase: appDatabase,
|
|
||||||
paneConnector: paneConnector)
|
|
||||||
|
|
||||||
print("meow back from update in main")
|
|
||||||
sr = try await appDatabase.getSelectedRibbon()
|
|
||||||
print("meow second sr:\(sr)")
|
|
||||||
print("meow backribbon br:\(br)")
|
|
||||||
|
|
||||||
_ = try await appDatabase.undoRibbon(&sr[0])
|
|
||||||
goToRibbon(selectedRibbon: sr[0],
|
|
||||||
destRibbon: br,
|
|
||||||
appDatabase: appDatabase,
|
|
||||||
paneConnector: paneConnector,
|
|
||||||
loading: false,
|
|
||||||
bump:false)
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
print("back 2 error")
|
|
||||||
print("Error info: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ForwardArrow()
|
|
||||||
.frame(width: CGFloat(30), height: CGFloat(30))
|
|
||||||
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4)))
|
|
||||||
}
|
|
||||||
.cornerRadius(5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,18 +2,30 @@ import Combine
|
||||||
import GRDB
|
import GRDB
|
||||||
import GRDBQuery
|
import GRDBQuery
|
||||||
|
|
||||||
|
/// A player request can be used with the `@Query` property wrapper in order to
|
||||||
|
/// feed a view with a list of players.
|
||||||
|
///
|
||||||
|
/// For example:
|
||||||
|
///
|
||||||
|
/// struct MyView: View {
|
||||||
|
/// @Query(RibbonRequest(ordering: .byName)) private var players: [Ribbon]
|
||||||
|
///
|
||||||
|
/// var body: some View {
|
||||||
|
/// List(players) { player in ... )
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
|
||||||
|
|
||||||
var idColumn = Column("id")
|
var idColumn = Column("id")
|
||||||
struct RibbonRequest: Queryable {
|
struct RibbonRequest: Queryable {
|
||||||
enum UndoDir {
|
// enum Ordering {
|
||||||
case prev
|
// case byScore
|
||||||
case next
|
// case byName
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// The ordering used by the player request.
|
/// The ordering used by the player request.
|
||||||
// var ordering: Ordering
|
// var ordering: Ordering
|
||||||
var id: Int64!
|
var id: Int64!
|
||||||
var dir: UndoDir?
|
|
||||||
var groupId: Int?
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Queryable Implementation
|
// MARK: - Queryable Implementation
|
||||||
|
@ -37,103 +49,12 @@ struct RibbonRequest: Queryable {
|
||||||
|
|
||||||
// This method is not required by Queryable, but it makes it easier
|
// This method is not required by Queryable, but it makes it easier
|
||||||
func fetchValue(_ db: Database) throws -> [Ribbon] {
|
func fetchValue(_ db: Database) throws -> [Ribbon] {
|
||||||
|
if (id == nil) {
|
||||||
var ret: [Ribbon]
|
return try Ribbon.order(Column("pos")).fetchAll(db)
|
||||||
var sql: String
|
} else {
|
||||||
|
return try Ribbon.filter(idColumn == id).fetchAll(db)
|
||||||
// this has to be a global variable
|
|
||||||
let totalLevels = 3
|
|
||||||
do {
|
|
||||||
print("back reload")
|
|
||||||
if dir != nil && groupId != nil {
|
|
||||||
sql = """
|
|
||||||
SELECT * FROM Ribbon \
|
|
||||||
WHERE groupId = ?
|
|
||||||
"""
|
|
||||||
ret = try Ribbon.fetchAll(db, sql: sql, arguments: [groupId])
|
|
||||||
if ret.count == 0 {
|
|
||||||
print("error no ribbons found")
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
print("back all ribbon all: \(ret)")
|
|
||||||
|
|
||||||
let currentLevel = ret[0].currentLevel
|
|
||||||
let minLevel = ret[0].minLevel
|
|
||||||
let maxLevel = ret[0].maxLevel
|
|
||||||
|
|
||||||
var newCurrentLevel = (currentLevel - 1) %% totalLevels
|
|
||||||
|
|
||||||
// probably need more error checking to check
|
|
||||||
// if current level gets into an error state
|
|
||||||
// between minLevel and maxLevel somehow but there
|
|
||||||
// are probably a bunch of edge cases casue of the
|
|
||||||
// mod stuff
|
|
||||||
if dir == .prev {
|
|
||||||
// no back undo steps left
|
|
||||||
if currentLevel == minLevel {
|
|
||||||
newCurrentLevel = currentLevel
|
|
||||||
}
|
|
||||||
} else if dir == .prev {
|
|
||||||
// no forward redo steps left
|
|
||||||
if currentLevel == maxLevel {
|
|
||||||
newCurrentLevel = maxLevel
|
|
||||||
} else {
|
|
||||||
newCurrentLevel = (currentLevel + 1) %% totalLevels
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
print("back newcurrentlevel \(newCurrentLevel)")
|
|
||||||
sql = """
|
|
||||||
SELECT * FROM Ribbon \
|
|
||||||
WHERE groupId = ? AND
|
|
||||||
undoLevel = ?
|
|
||||||
LIMIT 1
|
|
||||||
"""
|
|
||||||
ret = try Ribbon.fetchAll(db, sql: sql, arguments: [groupId, newCurrentLevel])
|
|
||||||
|
|
||||||
print("back ribbon return: \(ret)")
|
|
||||||
return ret
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if groupId != nil {
|
|
||||||
let sql = """
|
|
||||||
SELECT * from Ribbon r1 \
|
|
||||||
WHERE r1.groupId = ?
|
|
||||||
ORDER BY undoLevel ASC
|
|
||||||
"""
|
|
||||||
|
|
||||||
var ret = try Ribbon.fetchAll(db, sql: sql, arguments: [groupId])
|
|
||||||
print("xxxxx fetching ribbons")
|
|
||||||
print(ret)
|
|
||||||
return ret
|
|
||||||
} else {
|
|
||||||
|
|
||||||
let sql = """
|
|
||||||
select distinct r1.* from Ribbon r1 join Ribbon r2 ON \
|
|
||||||
r1.undoLevel = r2.currentLevel AND r1.id = r2.id ORDER BY pos ASC
|
|
||||||
"""
|
|
||||||
var ret = try Ribbon.fetchAll(db, sql: sql)
|
|
||||||
print("xxxxx fetching ribbons")
|
|
||||||
print(ret)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
print(error.localizedDescription)
|
|
||||||
print(error)
|
|
||||||
print("Error")
|
|
||||||
return []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if id == nil {
|
|
||||||
// return try Ribbon.order(Column("pos")).fetchAll(db)
|
|
||||||
// } else {
|
|
||||||
// return try Ribbon.filter(idColumn == id).fetchAll(db)
|
|
||||||
// }
|
|
||||||
// {
|
|
||||||
|
|
||||||
// if book == "" {
|
// if book == "" {
|
||||||
// return try Ribbon.filter(bookColumn == Ribbon.randomBook()).fetchAll(db)
|
// return try Ribbon.filter(bookColumn == Ribbon.randomBook()).fetchAll(db)
|
||||||
// } else {
|
// } else {
|
||||||
|
@ -148,14 +69,3 @@ struct RibbonRequest: Queryable {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
infix operator %%
|
|
||||||
|
|
||||||
extension Int {
|
|
||||||
|
|
||||||
static func %% (_ left: Int, _ right: Int) -> Int {
|
|
||||||
let mod = left % right
|
|
||||||
return mod >= 0 ? mod : mod + right
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,37 +24,15 @@ struct SegDenormRequest: Queryable {
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchValue(_ db: Database) throws -> [SegDenorm] {
|
func fetchValue(_ db: Database) throws -> [SegDenorm] {
|
||||||
print("segs denorm fetching for \(book)")
|
print("WOOOOOOF")
|
||||||
print(book)
|
var sql = "select seg_id as id, seg.book as book, group_concat(line.body, ';;') as body from seg join line on seg.line_id = line.rowid WHERE seg.book = 'bible.john' group by seg.seg_id"
|
||||||
var sql = """
|
|
||||||
select seg_id as id, seg.book as book, group_concat(line.body, ';;') as body from \
|
|
||||||
(select * from seg where seg.book = '\(book)') as seg \
|
|
||||||
join (select * from line where line.book = '\(book)') as line \
|
|
||||||
on seg.line_id = line.line_id group by seg.seg_id
|
|
||||||
"""
|
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
var ret = try SegDenorm.fetchAll(db, sql: sql) // [Player]
|
||||||
var ret = try SegDenorm.fetchAll(db, sql: sql)
|
|
||||||
|
|
||||||
// print("SEGS DENORM")
|
// print("SEGS DENORM")
|
||||||
// print(ret[0])
|
// print(ret)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// var sql2 = """
|
|
||||||
// select count(1) from seg where seg.book = '\(book)'
|
|
||||||
// """
|
|
||||||
|
|
||||||
// var ret2 = try SegDenorm.fetchAll(db, sql: sql2)
|
|
||||||
|
|
||||||
// print("test sql result")
|
|
||||||
// print(ret2[0])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
} catch let error {
|
} catch let error {
|
||||||
print(error.localizedDescription)
|
print(error.localizedDescription)
|
||||||
print(error)
|
print(error)
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
@State var selection = 0
|
|
||||||
var body: some View {
|
|
||||||
HStack {
|
|
||||||
BackArrow()
|
|
||||||
.frame(width: CGFloat(30), height: CGFloat(30))
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4)))
|
|
||||||
.if(selection == 0) { $0.background(Color.white) }
|
|
||||||
.if(selection != 0) { $0.background(Color.black) }
|
|
||||||
.onTapGesture {
|
|
||||||
withAnimation(.spring(response: 0.5)) {
|
|
||||||
self.selection = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ForwardArrow()
|
|
||||||
.frame(width: CGFloat(30), height: CGFloat(30))
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4)))
|
|
||||||
.if(selection == 1) { $0.background(Color.white) }
|
|
||||||
.if(selection != 1) { $0.background(Color.black) }
|
|
||||||
.onTapGesture {
|
|
||||||
withAnimation(.spring(response: 0.5)) {
|
|
||||||
self.selection = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@ struct SelectedRibbon: 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 ribbonGroupId: Int64
|
var ribbonId: Int64
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SelectedRibbon {
|
extension SelectedRibbon {
|
||||||
|
@ -32,7 +32,7 @@ extension SelectedRibbon: Codable, FetchableRecord, MutablePersistableRecord {
|
||||||
// Define database columns from CodingKeys
|
// Define database columns from CodingKeys
|
||||||
fileprivate enum Columns {
|
fileprivate enum Columns {
|
||||||
static let id = Column(CodingKeys.id)
|
static let id = Column(CodingKeys.id)
|
||||||
static let ribbonGroupId = Column(CodingKeys.ribbonGroupId)
|
static let ribbonId = Column(CodingKeys.ribbonId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates a player id after it has been inserted in the database.
|
/// Updates a player id after it has been inserted in the database.
|
||||||
|
|
|
@ -51,16 +51,11 @@ struct SelectedRibbonRequest: Queryable {
|
||||||
// var ret3 = try Ribbon.fetchAll(db, sql: "SELECT * FROM Ribbon") // [Player]
|
// var ret3 = try Ribbon.fetchAll(db, sql: "SELECT * FROM Ribbon") // [Player]
|
||||||
// print(ret3)
|
// print(ret3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// print("FETCH JOIN RIBBON")
|
// print("FETCH JOIN RIBBON")
|
||||||
var ret = try Ribbon.fetchAll(db, sql: """
|
var ret = try Ribbon.fetchAll(db, sql: "SELECT Ribbon.* FROM SelectedRibbon join Ribbon on SelectedRibbon.ribbonId = ribbon.rowId WHERE SelectedRibbon.rowId = 1") // [Player]
|
||||||
SELECT Ribbon.* FROM SelectedRibbon \
|
// print(ret)
|
||||||
JOIN (select distinct r1.* from Ribbon r1 join Ribbon r2 ON \
|
|
||||||
r1.undoLevel = r2.currentLevel AND r1.id = r2.id ORDER BY pos ASC) as Ribbon \
|
|
||||||
ON SelectedRibbon.ribbonGroupId = Ribbon.groupId \
|
|
||||||
WHERE SelectedRibbon.rowId = 1
|
|
||||||
""")
|
|
||||||
// [Player]
|
|
||||||
print("Selected Ribbon query result: \(ret)")
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
113
Stats.swift
113
Stats.swift
|
@ -1,113 +0,0 @@
|
||||||
import GRDB
|
|
||||||
import GRDBQuery
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
var fontSize = CGFloat(12)
|
|
||||||
|
|
||||||
struct StatsPanel: View {
|
|
||||||
@ObservedObject var paneConnector: PaneConnector
|
|
||||||
|
|
||||||
@Query(RibbonRequest(dir: .prev, groupId: 1)) private var backRibbon: [Ribbon]
|
|
||||||
@Query(RibbonRequest(dir: .next, groupId: 1)) private var nextRibbon: [Ribbon]
|
|
||||||
@Query(RibbonRequest(groupId: 1)) private var allRibbons: [Ribbon]
|
|
||||||
@Query(SelectedRibbonRequest()) private var selectedRibbon: [Ribbon]
|
|
||||||
@Environment(\.appDatabase) private var appDatabase
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
VStack (spacing: 10) {
|
|
||||||
VStack {
|
|
||||||
Text("back Ribbon")
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
|
||||||
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
|
||||||
RibbonDebug(ribbonDebug: RibbonDebugPrint(ribbon: backRibbon[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack {
|
|
||||||
Text("next Ribbon")
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
|
||||||
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
|
||||||
if (nextRibbon.count > 0) {
|
|
||||||
RibbonDebug(ribbonDebug: RibbonDebugPrint(ribbon: nextRibbon[0]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack {
|
|
||||||
Text("selected Ribbon")
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
|
||||||
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
|
||||||
RibbonDebug(ribbonDebug: RibbonDebugPrint(ribbon: selectedRibbon[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ForEach(RibbonMap(ribbons: allRibbons), id: \.self) { ribbon in
|
|
||||||
Print("quack3: \(ribbon)")
|
|
||||||
RibbonDebug(ribbonDebug: ribbon)
|
|
||||||
}
|
|
||||||
|
|
||||||
//VStack(spacing: 10) {
|
|
||||||
// Text("All Ribbons")
|
|
||||||
// .foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
|
||||||
// .font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
|
||||||
|
|
||||||
// ForEach(RibbonMap(ribbons: allRibbons), id: \.self) { ribbon in
|
|
||||||
// //Print("quack2: \(ribbon)")
|
|
||||||
// RibbonDebug(ribbonDebug: RibbonDebugPrint(ribbon: ribbon))
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
VStack {
|
|
||||||
Text("pc offset: \(paneConnector.currentOffset)")
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
|
||||||
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack {
|
|
||||||
Text("pc id: \(paneConnector.currentId)")
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
|
||||||
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func RibbonMap(ribbons: [Ribbon]) -> [[String]] {
|
|
||||||
var retStrings = [[String]]()
|
|
||||||
for r in ribbons {
|
|
||||||
var debugString = RibbonDebugPrint(ribbon:r)
|
|
||||||
retStrings.append(debugString)
|
|
||||||
}
|
|
||||||
return retStrings
|
|
||||||
}
|
|
||||||
|
|
||||||
func RibbonDebugPrint(ribbon: Ribbon) -> [String] {
|
|
||||||
var ribbonStats = [String]()
|
|
||||||
ribbonStats.append("id: \(ribbon.id) ")
|
|
||||||
ribbonStats.append("scrollOffset: \(ribbon.scrollOffset)")
|
|
||||||
ribbonStats.append("scrollId: \(ribbon.scrollId)")
|
|
||||||
ribbonStats.append("undoLevel: \(ribbon.undoLevel)")
|
|
||||||
ribbonStats.append("currentLevel: \(ribbon.currentLevel)")
|
|
||||||
ribbonStats.append("minLevel: \(ribbon.minLevel)")
|
|
||||||
ribbonStats.append("maxLevel: \(ribbon.maxLevel)")
|
|
||||||
return ribbonStats
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RibbonDebug: View {
|
|
||||||
@State var ribbonDebug: [String]
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
|
|
||||||
VStack {
|
|
||||||
VStack {
|
|
||||||
// let ribbonStats = RibbonDebugPrint(ribbon: ribbon)
|
|
||||||
|
|
||||||
Print("quack2: \(ribbonDebug)")
|
|
||||||
ForEach(ribbonDebug, id: \.self) {
|
|
||||||
Print("quack2 : \($0)")
|
|
||||||
Text($0)
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
|
||||||
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,10 +7,6 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
851259B02C05281300BE70F8 /* BackButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259AF2C05281300BE70F8 /* BackButton.swift */; };
|
|
||||||
851259B22C05299200BE70F8 /* ForwardArrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259B12C05299200BE70F8 /* ForwardArrow.swift */; };
|
|
||||||
851259B62C07560800BE70F8 /* NaviBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259B52C07560800BE70F8 /* NaviBar.swift */; };
|
|
||||||
851259B82C0A145500BE70F8 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259B72C0A145500BE70F8 /* Stats.swift */; };
|
|
||||||
8514D5BC299EFB780054F185 /* store.db in Resources */ = {isa = PBXBuildFile; fileRef = 8514D5BB299EFB780054F185 /* store.db */; };
|
8514D5BC299EFB780054F185 /* store.db in Resources */ = {isa = PBXBuildFile; fileRef = 8514D5BB299EFB780054F185 /* store.db */; };
|
||||||
8514D5BF299F04710054F185 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = 8514D5BE299F04710054F185 /* GRDB */; };
|
8514D5BF299F04710054F185 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = 8514D5BE299F04710054F185 /* GRDB */; };
|
||||||
852774C129A150B100458CA7 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852774C029A150B100458CA7 /* Line.swift */; };
|
852774C129A150B100458CA7 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852774C029A150B100458CA7 /* Line.swift */; };
|
||||||
|
@ -49,10 +45,6 @@
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
851259AF2C05281300BE70F8 /* BackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackButton.swift; sourceTree = "<group>"; };
|
|
||||||
851259B12C05299200BE70F8 /* ForwardArrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForwardArrow.swift; sourceTree = "<group>"; };
|
|
||||||
851259B52C07560800BE70F8 /* NaviBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NaviBar.swift; sourceTree = "<group>"; };
|
|
||||||
851259B72C0A145500BE70F8 /* Stats.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; };
|
|
||||||
8514D5BB299EFB780054F185 /* store.db */ = {isa = PBXFileReference; lastKnownFileType = file; path = store.db; sourceTree = "<group>"; };
|
8514D5BB299EFB780054F185 /* store.db */ = {isa = PBXFileReference; lastKnownFileType = file; path = store.db; sourceTree = "<group>"; };
|
||||||
852774C029A150B100458CA7 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
852774C029A150B100458CA7 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||||
8528897429B2B86B003F2E16 /* CrownOfThorns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrownOfThorns.swift; sourceTree = "<group>"; };
|
8528897429B2B86B003F2E16 /* CrownOfThorns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrownOfThorns.swift; sourceTree = "<group>"; };
|
||||||
|
@ -116,8 +108,6 @@
|
||||||
85431A7C2905F4F500EE0760 = {
|
85431A7C2905F4F500EE0760 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
851259B12C05299200BE70F8 /* ForwardArrow.swift */,
|
|
||||||
851259AF2C05281300BE70F8 /* BackButton.swift */,
|
|
||||||
857C34482BFB7DC800661A63 /* Fenestra.swift */,
|
857C34482BFB7DC800661A63 /* Fenestra.swift */,
|
||||||
8594ED972BF6845F001213F2 /* HexColor.swift */,
|
8594ED972BF6845F001213F2 /* HexColor.swift */,
|
||||||
85E00E7B29F34D2D00FF9E78 /* ScrollState.swift */,
|
85E00E7B29F34D2D00FF9E78 /* ScrollState.swift */,
|
||||||
|
@ -127,8 +117,6 @@
|
||||||
85942EEE29AEA18300307621 /* SelectedRibbonRequest.swift */,
|
85942EEE29AEA18300307621 /* SelectedRibbonRequest.swift */,
|
||||||
85942EF429B108C600307621 /* Seg.swift */,
|
85942EF429B108C600307621 /* Seg.swift */,
|
||||||
85942EF629B108EA00307621 /* SegDenormRequest.swift */,
|
85942EF629B108EA00307621 /* SegDenormRequest.swift */,
|
||||||
851259B52C07560800BE70F8 /* NaviBar.swift */,
|
|
||||||
851259B72C0A145500BE70F8 /* Stats.swift */,
|
|
||||||
85942EF829B1150B00307621 /* SegDenorm.swift */,
|
85942EF829B1150B00307621 /* SegDenorm.swift */,
|
||||||
85942EEA29AD55A400307621 /* RibbonRequest.swift */,
|
85942EEA29AD55A400307621 /* RibbonRequest.swift */,
|
||||||
85942EE329ACF54A00307621 /* ScrollableView.swift */,
|
85942EE329ACF54A00307621 /* ScrollableView.swift */,
|
||||||
|
@ -297,7 +285,6 @@
|
||||||
857C34492BFB7DC800661A63 /* Fenestra.swift in Sources */,
|
857C34492BFB7DC800661A63 /* Fenestra.swift in Sources */,
|
||||||
85942EEB29AD55A400307621 /* RibbonRequest.swift in Sources */,
|
85942EEB29AD55A400307621 /* RibbonRequest.swift in Sources */,
|
||||||
85431A8B2905F4F500EE0760 /* ContentView.swift in Sources */,
|
85431A8B2905F4F500EE0760 /* ContentView.swift in Sources */,
|
||||||
851259B02C05281300BE70F8 /* BackButton.swift in Sources */,
|
|
||||||
85942EF529B108C600307621 /* Seg.swift in Sources */,
|
85942EF529B108C600307621 /* Seg.swift in Sources */,
|
||||||
85E00E7C29F34D2D00FF9E78 /* ScrollState.swift in Sources */,
|
85E00E7C29F34D2D00FF9E78 /* ScrollState.swift in Sources */,
|
||||||
8594ED982BF6845F001213F2 /* HexColor.swift in Sources */,
|
8594ED982BF6845F001213F2 /* HexColor.swift in Sources */,
|
||||||
|
@ -310,15 +297,12 @@
|
||||||
85942EEF29AEA18300307621 /* SelectedRibbonRequest.swift in Sources */,
|
85942EEF29AEA18300307621 /* SelectedRibbonRequest.swift in Sources */,
|
||||||
8590D96C29A92146001EF84F /* JsonImport.swift in Sources */,
|
8590D96C29A92146001EF84F /* JsonImport.swift in Sources */,
|
||||||
85942EED29AEA04200307621 /* SelectedRibbon.swift in Sources */,
|
85942EED29AEA04200307621 /* SelectedRibbon.swift in Sources */,
|
||||||
851259B82C0A145500BE70F8 /* Stats.swift in Sources */,
|
|
||||||
85431A892905F4F500EE0760 /* glossApp.swift in Sources */,
|
85431A892905F4F500EE0760 /* glossApp.swift in Sources */,
|
||||||
8528897C29BD69B2003F2E16 /* VisibilityTrackingScrollView.swift in Sources */,
|
8528897C29BD69B2003F2E16 /* VisibilityTrackingScrollView.swift in Sources */,
|
||||||
85942EF929B1150B00307621 /* SegDenorm.swift in Sources */,
|
85942EF929B1150B00307621 /* SegDenorm.swift in Sources */,
|
||||||
85431A9C2905F5D800EE0760 /* SwiftUIView.swift in Sources */,
|
85431A9C2905F5D800EE0760 /* SwiftUIView.swift in Sources */,
|
||||||
851259B22C05299200BE70F8 /* ForwardArrow.swift in Sources */,
|
|
||||||
8528897E29BD69B2003F2E16 /* VisibilityTracker.swift in Sources */,
|
8528897E29BD69B2003F2E16 /* VisibilityTracker.swift in Sources */,
|
||||||
85942EF729B108EA00307621 /* SegDenormRequest.swift in Sources */,
|
85942EF729B108EA00307621 /* SegDenormRequest.swift in Sources */,
|
||||||
851259B62C07560800BE70F8 /* NaviBar.swift in Sources */,
|
|
||||||
8528897D29BD69B2003F2E16 /* VisibilityTrackingModifier.swift in Sources */,
|
8528897D29BD69B2003F2E16 /* VisibilityTrackingModifier.swift in Sources */,
|
||||||
85942EE429ACF54A00307621 /* ScrollableView.swift in Sources */,
|
85942EE429ACF54A00307621 /* ScrollableView.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import GRDB
|
import GRDB
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let totalLevels = 3
|
|
||||||
|
|
||||||
/// AppDatabase lets the application access the database.
|
/// AppDatabase lets the application access the database.
|
||||||
///
|
///
|
||||||
/// It applies the pratices recommended at
|
/// It applies the pratices recommended at
|
||||||
|
@ -43,7 +39,6 @@ struct AppDatabase {
|
||||||
t.autoIncrementedPrimaryKey("id")
|
t.autoIncrementedPrimaryKey("id")
|
||||||
t.column("body", .text).notNull()
|
t.column("body", .text).notNull()
|
||||||
t.column("chap", .integer).notNull()
|
t.column("chap", .integer).notNull()
|
||||||
t.column("line_id", .integer).notNull()
|
|
||||||
t.column("book", .text).notNull()
|
t.column("book", .text).notNull()
|
||||||
t.column("verse", .integer)
|
t.column("verse", .integer)
|
||||||
}
|
}
|
||||||
|
@ -58,13 +53,6 @@ struct AppDatabase {
|
||||||
try db.create(table: "Ribbon") { t in
|
try db.create(table: "Ribbon") { t in
|
||||||
t.autoIncrementedPrimaryKey("id")
|
t.autoIncrementedPrimaryKey("id")
|
||||||
t.column("pos", .integer).notNull()
|
t.column("pos", .integer).notNull()
|
||||||
t.column("groupId", .integer).notNull()
|
|
||||||
t.column("undoLevel", .integer).notNull()
|
|
||||||
|
|
||||||
t.column("currentLevel", .integer).notNull()
|
|
||||||
t.column("minLevel", .integer).notNull()
|
|
||||||
t.column("maxLevel", .integer).notNull()
|
|
||||||
.defaults(to: 1)
|
|
||||||
t.column("title", .text).notNull()
|
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()
|
||||||
|
@ -73,7 +61,7 @@ struct AppDatabase {
|
||||||
|
|
||||||
try db.create(table: "SelectedRibbon") { t in
|
try db.create(table: "SelectedRibbon") { t in
|
||||||
t.autoIncrementedPrimaryKey("id")
|
t.autoIncrementedPrimaryKey("id")
|
||||||
t.column("ribbonGroupId", .integer).notNull()
|
t.column("ribbonId", .integer).notNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
try db.create(table: "ScrollState") { t in
|
try db.create(table: "ScrollState") { t in
|
||||||
|
@ -82,8 +70,7 @@ struct AppDatabase {
|
||||||
t.column("scrollOffset", .integer).notNull()
|
t.column("scrollOffset", .integer).notNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
// change this to nuke/remake the database
|
try db.create(table: "foo2") { t in
|
||||||
try db.create(table: "foo1") { t in
|
|
||||||
t.autoIncrementedPrimaryKey("id")
|
t.autoIncrementedPrimaryKey("id")
|
||||||
t.column("ribbonId", .integer).notNull()
|
t.column("ribbonId", .integer).notNull()
|
||||||
}
|
}
|
||||||
|
@ -126,22 +113,6 @@ func load<T: Decodable>(_ filename: String) -> T {
|
||||||
|
|
||||||
extension AppDatabase {
|
extension AppDatabase {
|
||||||
|
|
||||||
func getSelectedRibbon() async throws -> [Ribbon] {
|
|
||||||
try await dbWriter.write { db in
|
|
||||||
var sr = try Ribbon.fetchAll(db, sql: """
|
|
||||||
SELECT Ribbon.* FROM SelectedRibbon \
|
|
||||||
JOIN (select distinct r1.* from Ribbon r1 join Ribbon r2 ON \
|
|
||||||
r1.undoLevel = r2.currentLevel AND r1.id = r2.id ORDER BY pos ASC) as Ribbon \
|
|
||||||
ON SelectedRibbon.ribbonGroupId = Ribbon.groupId \
|
|
||||||
WHERE SelectedRibbon.rowId = 1
|
|
||||||
""")
|
|
||||||
|
|
||||||
print("meow get selected ribbon \(sr)")
|
|
||||||
return sr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func updateRibbonPosition(_ ribbon: inout Ribbon, _ oldPos: Int, _ newPos: Int) async throws {
|
func updateRibbonPosition(_ ribbon: inout Ribbon, _ oldPos: Int, _ newPos: Int) async throws {
|
||||||
try await dbWriter.write { [ribbon] db in
|
try await dbWriter.write { [ribbon] db in
|
||||||
|
|
||||||
|
@ -222,121 +193,6 @@ extension AppDatabase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoRibbon(_ ribbon: inout Ribbon) async throws {
|
|
||||||
let currentLevel = ribbon.currentLevel
|
|
||||||
let minLevel = ribbon.minLevel
|
|
||||||
if currentLevel == minLevel {
|
|
||||||
print("no where to undo")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let newCurrent = (ribbon.currentLevel - 1) %% totalLevels
|
|
||||||
print("meow new current: \(newCurrent)")
|
|
||||||
|
|
||||||
do {
|
|
||||||
try await dbWriter.write { [ribbon] db in
|
|
||||||
print("back executing")
|
|
||||||
try db.execute(sql: """
|
|
||||||
UPDATE Ribbon \
|
|
||||||
SET currentLevel = ? WHERE groupId = ?
|
|
||||||
""", arguments: [newCurrent, ribbon.groupId])
|
|
||||||
|
|
||||||
var ret3 = try Ribbon.fetchAll(db, sql: """
|
|
||||||
SELECT * from Ribbon \
|
|
||||||
WHERE groupId = ?
|
|
||||||
""", arguments: [ribbon.groupId])
|
|
||||||
|
|
||||||
print("back ret3: \(ret3)")
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
print("back error")
|
|
||||||
print("Error info: \(error)")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func bumpRibbon(_ ribbon: inout Ribbon) async throws -> [Ribbon] {
|
|
||||||
var level = ribbon.currentLevel
|
|
||||||
let maxLevel = ribbon.maxLevel
|
|
||||||
var delLevels2 = [Int]()
|
|
||||||
while level != maxLevel {
|
|
||||||
level = (level + 1) % totalLevels
|
|
||||||
delLevels2.append(level)
|
|
||||||
}
|
|
||||||
let delLevels = delLevels2
|
|
||||||
|
|
||||||
let newMax = (ribbon.currentLevel + 1) %% totalLevels
|
|
||||||
let newCurrent = newMax
|
|
||||||
let newMin = newMax == ribbon.minLevel ? (ribbon.minLevel + 1) %% totalLevels
|
|
||||||
: ribbon.minLevel
|
|
||||||
|
|
||||||
ribbon.minLevel = newMin
|
|
||||||
ribbon.maxLevel = newMax
|
|
||||||
ribbon.undoLevel = newCurrent
|
|
||||||
ribbon.currentLevel = newCurrent
|
|
||||||
ribbon.id = nil
|
|
||||||
|
|
||||||
do {
|
|
||||||
try await dbWriter.write { [ribbon] db in
|
|
||||||
print("meow enter bump 1")
|
|
||||||
for l in delLevels {
|
|
||||||
try db.execute(sql: """
|
|
||||||
DELETE FROM Ribbon \
|
|
||||||
WHERE groupId = ? \
|
|
||||||
AND undoLevel = ?
|
|
||||||
""", arguments: [ribbon.groupId, l])
|
|
||||||
}
|
|
||||||
|
|
||||||
try db.execute(sql: """
|
|
||||||
UPDATE Ribbon \
|
|
||||||
SET minLevel = ?, maxLevel = ?, currentLevel = ? WHERE groupId = ?
|
|
||||||
""", arguments: [newMin, newMax, newCurrent, ribbon.groupId])
|
|
||||||
|
|
||||||
|
|
||||||
// upsert
|
|
||||||
var ret = try Ribbon.fetchAll(db, sql: """
|
|
||||||
SELECT * from Ribbon WHERE groupId = ? AND undoLevel = ?
|
|
||||||
""", arguments: [ribbon.groupId, ribbon.undoLevel])
|
|
||||||
|
|
||||||
print("meow enter bump 3")
|
|
||||||
if ret.count == 0 {
|
|
||||||
// insert
|
|
||||||
_ = try ribbon.inserted(db)
|
|
||||||
} else {
|
|
||||||
var updatedRibbon = ret[0]
|
|
||||||
updatedRibbon.minLevel = newMin
|
|
||||||
updatedRibbon.maxLevel = newMax
|
|
||||||
updatedRibbon.undoLevel = newCurrent
|
|
||||||
updatedRibbon.currentLevel = newCurrent
|
|
||||||
updatedRibbon.scrollId = ribbon.scrollId
|
|
||||||
updatedRibbon.scrollOffset = ribbon.scrollOffset
|
|
||||||
try updatedRibbon.update(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = try Ribbon.fetchAll(db, sql: """
|
|
||||||
SELECT * from Ribbon WHERE groupId = ? AND undoLevel = ?
|
|
||||||
""", arguments: [ribbon.groupId, ribbon.undoLevel])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let ret2 = try Ribbon.fetchAll(db, sql: """
|
|
||||||
SELECT * from Ribbon WHERE groupId = 1 ORDER BY undoLevel ASC
|
|
||||||
""")
|
|
||||||
|
|
||||||
for r2 in ret2 {
|
|
||||||
print("meow ribbon dump: \(r2)")
|
|
||||||
}
|
|
||||||
|
|
||||||
print("meow bumped ribbon: \(ret)")
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
print("Error info: \(error)")
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveSelectedRibbon(_ selectedRibbon: inout SelectedRibbon) async throws {
|
func saveSelectedRibbon(_ selectedRibbon: inout SelectedRibbon) async throws {
|
||||||
// if ribbon.name.isEmpty {
|
// if ribbon.name.isEmpty {
|
||||||
// throw ValidationError.missingName
|
// throw ValidationError.missingName
|
||||||
|
@ -356,106 +212,35 @@ extension AppDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
func importJson(_ filename: String, _ db: Database) throws {
|
func importJson(_ filename: String, _ db: Database) throws {
|
||||||
let importJson: JsonImport = load(filename)
|
let importJson : JsonImport = load(filename)
|
||||||
|
|
||||||
var x = 0
|
if try Line.all().isEmpty(db) {
|
||||||
// if try Line.all().isEmpty(db) {
|
for l in importJson.lines {
|
||||||
for l in importJson.lines {
|
print("importing Lines")
|
||||||
// print("importing Lines")
|
_ = try l.inserted(db)
|
||||||
if x < 5 {
|
|
||||||
print(l)
|
|
||||||
x += 1
|
|
||||||
}
|
}
|
||||||
_ = try l.inserted(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
x = 0
|
for l in importJson.segs {
|
||||||
for l in importJson.segs {
|
print("importing SEGS")
|
||||||
// print("importing SEGS")
|
_ = try l.inserted(db)
|
||||||
|
|
||||||
if x < 5 {
|
|
||||||
print(l)
|
|
||||||
x += 1
|
|
||||||
}
|
}
|
||||||
_ = try l.inserted(db)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create random Lines if the database is empty.
|
/// Create random Lines if the database is empty.
|
||||||
func initDatabase() throws {
|
func initDatabase() throws {
|
||||||
do {
|
try dbWriter.write { db in
|
||||||
try dbWriter.write { db in
|
|
||||||
if try Line.all().isEmpty(db)
|
|
||||||
{
|
|
||||||
try importJson("john_export.json", db)
|
|
||||||
try importJson("mark_export.json", db)
|
|
||||||
_ = try Ribbon(id: 1,
|
|
||||||
groupId: 1,
|
|
||||||
pos: 1,
|
|
||||||
undoLevel: 0,
|
|
||||||
currentLevel: 0,
|
|
||||||
minLevel: 0,
|
|
||||||
maxLevel: 0,
|
|
||||||
title: "John",
|
|
||||||
book: "bible.john",
|
|
||||||
scrollId: "1",
|
|
||||||
scrollOffset: 0).inserted(db)
|
|
||||||
_ = try Ribbon(id: 2,
|
|
||||||
groupId: 2,
|
|
||||||
pos: 2,
|
|
||||||
undoLevel: 0,
|
|
||||||
currentLevel: 0,
|
|
||||||
minLevel: 0,
|
|
||||||
maxLevel: 0,
|
|
||||||
title: "Gospel of Mark",
|
|
||||||
book: "bible.mark",
|
|
||||||
scrollId: "1",
|
|
||||||
scrollOffset: 300).inserted(db)
|
|
||||||
|
|
||||||
/////
|
if try Line.all().isEmpty(db) {
|
||||||
|
|
||||||
_ = try Ribbon(id: 3,
|
try importJson("john_export.json", db)
|
||||||
groupId: 3,
|
try importJson("mark_export.json", db)
|
||||||
pos: 3,
|
_ = try Ribbon(id: 1, pos: 1, title: "John", book: "bible.john", scrollId: "1", scrollOffset: 0).inserted(db)
|
||||||
undoLevel: 0,
|
_ = try Ribbon(id: 2, pos: 2, title: "Gospel of Mark", book: "bible.mark", scrollId: "1", scrollOffset: 300).inserted(db)
|
||||||
currentLevel: 2,
|
_ = try Ribbon(id: 3, pos: 3, title: "John 2", book: "bible.john", scrollId: "1", scrollOffset: 0).inserted(db)
|
||||||
minLevel: 0,
|
_ = try SelectedRibbon(id: 1, ribbonId: 1).inserted(db)
|
||||||
maxLevel: 2,
|
|
||||||
title: "bottom",
|
|
||||||
book: "bible.john",
|
|
||||||
scrollId: "1",
|
|
||||||
scrollOffset: 0).inserted(db)
|
|
||||||
|
|
||||||
_ = try Ribbon(id: 4,
|
|
||||||
groupId: 3,
|
|
||||||
pos: 3,
|
|
||||||
undoLevel: 1,
|
|
||||||
currentLevel: 2,
|
|
||||||
minLevel: 0,
|
|
||||||
maxLevel: 2,
|
|
||||||
title: "topp",
|
|
||||||
book: "bible.john",
|
|
||||||
scrollId: "1",
|
|
||||||
scrollOffset: 0).inserted(db)
|
|
||||||
|
|
||||||
_ = try Ribbon(id: 5,
|
|
||||||
groupId: 3,
|
|
||||||
pos: 3,
|
|
||||||
undoLevel: 2,
|
|
||||||
currentLevel: 2,
|
|
||||||
minLevel: 0,
|
|
||||||
maxLevel: 2,
|
|
||||||
title: "topp",
|
|
||||||
book: "bible.john",
|
|
||||||
scrollId: "1",
|
|
||||||
scrollOffset: 0).inserted(db)
|
|
||||||
|
|
||||||
_ = try SelectedRibbon(id: 1, ribbonGroupId: 1).inserted(db)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
print("Error info: \(error)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,45 +39,20 @@ public extension UserDefaults {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateRibbon(selectedRibbon: Ribbon,
|
|
||||||
appDatabase : AppDatabase,
|
|
||||||
paneConnector: PaneConnector) async throws -> [Ribbon]
|
|
||||||
{
|
|
||||||
print("meow updating ribbon")
|
|
||||||
var updatedRibbon = selectedRibbon
|
|
||||||
var scrollOffsetToSave = Int(floor(paneConnector.currentOffset))
|
|
||||||
var scrollIdToSave = paneConnector.currentId
|
|
||||||
print("meow scrolloffsets \(scrollIdToSave) \(scrollOffsetToSave)")
|
|
||||||
var offsetDiff = abs(scrollOffsetToSave - updatedRibbon.scrollOffset) > 30
|
|
||||||
var idDiff = Int(updatedRibbon.scrollId) != Int(scrollIdToSave)
|
|
||||||
|
|
||||||
if idDiff || offsetDiff {
|
|
||||||
updatedRibbon.scrollId = scrollIdToSave
|
|
||||||
updatedRibbon.scrollOffset = scrollOffsetToSave
|
|
||||||
|
|
||||||
print("meow bumping")
|
|
||||||
let ret = try await appDatabase.bumpRibbon(&updatedRibbon)
|
|
||||||
print("meow finished bumping")
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
print("meow no bump")
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
func goToRibbon(selectedRibbon: Ribbon,
|
func goToRibbon(selectedRibbon: Ribbon,
|
||||||
destRibbon: Ribbon,
|
destRibbon: Ribbon,
|
||||||
appDatabase: AppDatabase,
|
appDatabase: AppDatabase,
|
||||||
paneConnector: PaneConnector,
|
paneConnector: PaneConnector,
|
||||||
loading: Bool,
|
refresh: Binding<Bool>,
|
||||||
bump: Bool)
|
loading: Bool)
|
||||||
{
|
{
|
||||||
print("meow goto ribbon - selected ribbon: \(selectedRibbon), dest ribbon: \(destRibbon) ")
|
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()) {
|
DispatchQueue.main.asyncAfter(deadline: .now()) {
|
||||||
Task {
|
Task {
|
||||||
var scrollOffsetToSave = paneConnector.currentOffset
|
var scrollOffsetToSave = paneConnector.currentOffset
|
||||||
var scrollIdToSave = paneConnector.currentId
|
var scrollIdToSave = paneConnector.currentId
|
||||||
|
|
||||||
|
var updatedRibbon = selectedRibbon
|
||||||
print("go to ribbon")
|
print("go to ribbon")
|
||||||
print("\(selectedRibbon.id) \(destRibbon.id!)")
|
print("\(selectedRibbon.id) \(destRibbon.id!)")
|
||||||
|
|
||||||
|
@ -97,7 +72,9 @@ func goToRibbon(selectedRibbon: Ribbon,
|
||||||
print("toggling")
|
print("toggling")
|
||||||
print("paneconnector: \(paneConnector.refresh)")
|
print("paneconnector: \(paneConnector.refresh)")
|
||||||
|
|
||||||
var updateSelectRibbon = SelectedRibbon(id: Int64(1), ribbonGroupId: Int64(destRibbon.groupId))
|
refresh.wrappedValue.toggle()
|
||||||
|
|
||||||
|
var updateSelectRibbon = SelectedRibbon(id: Int64(1), ribbonId: destRibbon.id!)
|
||||||
// print("Saving selected ribbon")
|
// print("Saving selected ribbon")
|
||||||
// print(updateSelectRibbon)
|
// print(updateSelectRibbon)
|
||||||
do {
|
do {
|
||||||
|
@ -107,26 +84,15 @@ func goToRibbon(selectedRibbon: Ribbon,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// // this gets run regardless of if we switch ribbons or not
|
if !loading {
|
||||||
// // so if you click the same ribbon or a different ribbon
|
print("not loading")
|
||||||
// if !loading || bump {
|
updatedRibbon.scrollOffset = Int(floor(scrollOffsetToSave))
|
||||||
// print("not loading")
|
updatedRibbon.scrollId = scrollIdToSave
|
||||||
|
_ = try await appDatabase.saveRibbon(&updatedRibbon)
|
||||||
|
|
||||||
|
} else {
|
||||||
// print("saving ribbon")
|
print("loading")
|
||||||
// // updating the ribbon location
|
}
|
||||||
// updatedRibbon.scrollOffset = Int(floor(scrollOffsetToSave))
|
|
||||||
// updatedRibbon.scrollId = scrollIdToSave
|
|
||||||
// // updatedRibbon.undoLevel = updatedRibbon.undoLevel + 1
|
|
||||||
// // updatedRibbon.currentLevel = updatedRibbon.currentLevel + 1
|
|
||||||
|
|
||||||
// if bump {
|
|
||||||
// _ = try await appDatabase.bumpRibbon(&updatedRibbon)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
// print("loading")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +117,7 @@ struct RibbonCrown: View {
|
||||||
|
|
||||||
@Environment(\.appDatabase) private var appDatabase
|
@Environment(\.appDatabase) private var appDatabase
|
||||||
|
|
||||||
@Query(SelectedRibbonRequest()) private var selectedRibbon: [Ribbon]
|
@Query(SelectedRibbonRequest()) private var sr: [Ribbon]
|
||||||
|
|
||||||
@State var saveOffset = CGFloat()
|
@State var saveOffset = CGFloat()
|
||||||
@Binding var refresh: Bool
|
@Binding var refresh: Bool
|
||||||
|
@ -183,18 +149,12 @@ struct RibbonCrown: View {
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
Task {
|
Task {
|
||||||
|
goToRibbon(selectedRibbon: sr[0],
|
||||||
let sr = selectedRibbon[0]
|
|
||||||
let updatedRibbon = try await updateRibbon(selectedRibbon: sr,
|
|
||||||
appDatabase: appDatabase,
|
|
||||||
paneConnector: paneConnector)
|
|
||||||
|
|
||||||
goToRibbon(selectedRibbon: sr,
|
|
||||||
destRibbon: ribbon,
|
destRibbon: ribbon,
|
||||||
appDatabase: appDatabase,
|
appDatabase: appDatabase,
|
||||||
paneConnector: paneConnector,
|
paneConnector: paneConnector,
|
||||||
loading: false,
|
refresh: $refresh,
|
||||||
bump: true)
|
loading: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(width: CGFloat(100 * 1.66 * scale + 10), height: CGFloat(100 * scale + 5))
|
.frame(width: CGFloat(100 * 1.66 * scale + 10), height: CGFloat(100 * scale + 5))
|
||||||
|
@ -231,7 +191,6 @@ class PaneConnector: NSObject, ObservableObject {
|
||||||
// var setScrollOffset: CGFloat
|
// var setScrollOffset: CGFloat
|
||||||
var showOverlay: Bool = false
|
var showOverlay: Bool = false
|
||||||
@Published var refresh: Bool = false
|
@Published var refresh: Bool = false
|
||||||
@Published var vertSep = CGFloat(20)
|
|
||||||
var currentId = ""
|
var currentId = ""
|
||||||
var currentOffset = CGFloat()
|
var currentOffset = CGFloat()
|
||||||
var visibilityTracker: VisibilityTracker<String>?
|
var visibilityTracker: VisibilityTracker<String>?
|
||||||
|
@ -245,21 +204,25 @@ struct ContentView: View {
|
||||||
@State var viewState = CGSize.zero
|
@State var viewState = CGSize.zero
|
||||||
@State var pulledOut = CGSize.zero
|
@State var pulledOut = CGSize.zero
|
||||||
|
|
||||||
@State var selection = 0
|
|
||||||
|
|
||||||
@StateObject var paneConnector = PaneConnector()
|
@StateObject var paneConnector = PaneConnector()
|
||||||
|
|
||||||
@State var refresh: Bool = false
|
@State var refresh: Bool = false
|
||||||
|
|
||||||
@State var readOffset = CGPoint()
|
@State var vertSep = CGFloat(20)
|
||||||
|
|
||||||
|
@State var endedDrag = true
|
||||||
|
|
||||||
|
@State var readOffset = CGPoint()
|
||||||
|
@State var dragOffset = CGFloat()
|
||||||
|
|
||||||
@Query(SegDenormRequest(book: "bible.john")) private var segs: [SegDenorm]
|
|
||||||
|
|
||||||
@State var draggedRibbon: Ribbon?
|
@State var draggedRibbon: Ribbon?
|
||||||
@State var isDragging = false
|
@State var isDragging = false
|
||||||
|
|
||||||
@Environment(\.appDatabase) private var appDatabase
|
@Environment(\.appDatabase) private var appDatabase
|
||||||
|
|
||||||
|
@Query(SegDenormRequest(book: "bible.mark")) private var segs: [SegDenorm]
|
||||||
|
|
||||||
@Query(RibbonRequest()) private var ribbons: [Ribbon]
|
@Query(RibbonRequest()) private var ribbons: [Ribbon]
|
||||||
@Query<SelectedRibbonRequest> var selectedRibbon: [Ribbon]
|
@Query<SelectedRibbonRequest> var selectedRibbon: [Ribbon]
|
||||||
|
|
||||||
|
@ -308,25 +271,13 @@ struct ContentView: View {
|
||||||
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
|
.background(Color(red: 0.1, green: 0.1, blue: 0.1))
|
||||||
.frame(alignment: .topLeading)
|
.frame(alignment: .topLeading)
|
||||||
|
|
||||||
VStack {
|
|
||||||
Text("pc offset: \(paneConnector.currentOffset)")
|
|
||||||
.foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
|
||||||
.font(Font.custom("AveriaSerifLibre-Regular", size: fontSize))
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack {
|
|
||||||
NaviBar(paneConnector: paneConnector)
|
|
||||||
StatsPanel(paneConnector: paneConnector)
|
|
||||||
}
|
|
||||||
.frame(maxWidth: 250)
|
|
||||||
.offset(x: geometry.size.width - 250)
|
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
// Top pane
|
// Top pane
|
||||||
Pane(paneConnector: paneConnector,
|
Pane(paneConnector: paneConnector,
|
||||||
|
segs: segs,
|
||||||
selectedRibbon: selectedRibbon,
|
selectedRibbon: selectedRibbon,
|
||||||
width: geometry.size.width - 50,
|
width: geometry.size.width - 50,
|
||||||
height: geometry.size.height / 2)
|
height: geometry.size.height / 2 - vertSep)
|
||||||
//////
|
//////
|
||||||
|
|
||||||
Text("separator").foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
Text("separator").foregroundColor(Color(UIColor(red: 0.76, green: 0.76, blue: 0.76, alpha: 1.00)))
|
||||||
|
@ -334,7 +285,7 @@ struct ContentView: View {
|
||||||
DragGesture()
|
DragGesture()
|
||||||
.onChanged { gesture in
|
.onChanged { gesture in
|
||||||
|
|
||||||
paneConnector.vertSep = paneConnector.vertSep - gesture.translation.height
|
vertSep = vertSep - gesture.translation.height
|
||||||
Print(gesture.translation.width)
|
Print(gesture.translation.width)
|
||||||
Print(gesture.translation.height)
|
Print(gesture.translation.height)
|
||||||
|
|
||||||
|
@ -384,30 +335,33 @@ struct ContentView: View {
|
||||||
DragGesture()
|
DragGesture()
|
||||||
.onChanged { gesture in
|
.onChanged { gesture in
|
||||||
|
|
||||||
print(viewState.width)
|
if endedDrag {
|
||||||
print(pulledOut.width)
|
endedDrag = false
|
||||||
// threshold of how much to swipe before the view drags
|
|
||||||
if abs(gesture.translation.width) > 10 {
|
//TODO: should this still be adjusted
|
||||||
|
//scrollOffset = readOffset.y - 20
|
||||||
|
}
|
||||||
|
Print(viewState.width)
|
||||||
|
if abs(gesture.translation.width) > 20 {
|
||||||
viewState.width = gesture.translation.width
|
viewState.width = gesture.translation.width
|
||||||
// if gesture.translation.width < -50, pulledOut.width == CGFloat(0) {
|
if gesture.translation.width < -50, pulledOut.width == CGFloat(0) {
|
||||||
// }
|
dragOffset = gesture.translation.width + 50
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onEnded { _ in
|
.onEnded { _ in
|
||||||
var setPulledOutWith = CGFloat(0)
|
endedDrag = true
|
||||||
if viewState.width < 0 && pulledOut.width > 0 {
|
var pulledOutWidth = CGFloat(0)
|
||||||
setPulledOutWith = CGFloat(0)
|
if viewState.width < 0 {
|
||||||
} else if viewState.width > 0 && pulledOut.width < 0 {
|
pulledOutWidth = CGFloat(0)
|
||||||
setPulledOutWith = CGFloat(0)
|
|
||||||
} else if viewState.width < 0 && pulledOut.width == 0 {
|
|
||||||
setPulledOutWith = CGFloat(-200)
|
|
||||||
} else if abs(viewState.width + pulledOut.width) > 30 {
|
} else if abs(viewState.width + pulledOut.width) > 30 {
|
||||||
setPulledOutWith = CGFloat(200)
|
pulledOutWidth = CGFloat(200)
|
||||||
}
|
}
|
||||||
|
|
||||||
withAnimation(.spring(response: 0.2)) {
|
withAnimation(.spring(response: 0.2)) {
|
||||||
pulledOut.width = setPulledOutWith
|
pulledOut.width = pulledOutWidth
|
||||||
viewState = .zero
|
viewState = .zero
|
||||||
|
dragOffset = .zero
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -435,7 +389,27 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleVisibilityChanged2(_: String, change _: VisibilityChange, tracker _: VisibilityTracker<String>) {}
|
func handleVisibilityChanged2(_: String, change _: VisibilityChange, tracker _: VisibilityTracker<String>) {}
|
||||||
|
|
||||||
|
func handleVisibilityChanged(_: String, change _: VisibilityChange, tracker: VisibilityTracker<String>) {
|
||||||
|
// var printRate: Int64 = 10
|
||||||
|
// gTracker = tracker
|
||||||
|
self.paneConnector.visibilityTracker = tracker
|
||||||
|
|
||||||
|
|
||||||
|
let visibleViews2 = Array(tracker.visibleViews.keys)
|
||||||
|
if visibleViews2.count == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// currentId = tracker.sortedViewIDs[tracker.sortedViewIDs.count - 1]
|
||||||
|
currentId = tracker.sortedViewIDs[0]
|
||||||
|
currentOffset = tracker.visibleViews[currentId!]!
|
||||||
|
|
||||||
|
self.paneConnector.currentId = tracker.sortedViewIDs[0]
|
||||||
|
self.paneConnector.currentOffset = tracker.visibleViews[currentId!]!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let itemFormatter: DateFormatter = {
|
private let itemFormatter: DateFormatter = {
|
||||||
|
|
|
@ -1,17 +1,39 @@
|
||||||
import GRDB
|
import GRDB
|
||||||
/// The Line struct.
|
/// The Line struct.
|
||||||
|
///
|
||||||
|
/// Identifiable conformance supports SwiftUI list animations, and type-safe
|
||||||
|
/// GRDB primary key methods.
|
||||||
|
/// Equatable conformance supports tests.
|
||||||
struct Line: Identifiable, Equatable {
|
struct Line: Identifiable, Equatable {
|
||||||
|
/// The player id.
|
||||||
|
///
|
||||||
|
/// Int64 is the recommended type for auto-incremented database ids.
|
||||||
|
/// Use nil for players that are not inserted yet in the database.
|
||||||
var id: Int64?
|
var id: Int64?
|
||||||
var chap: Int
|
var chap: Int
|
||||||
var line_id: Int // this is a line_id per book
|
|
||||||
var verse: Int
|
var verse: Int
|
||||||
var body: String
|
var body: String
|
||||||
var book: String
|
var book: String
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Line {
|
extension Line {
|
||||||
|
|
||||||
private static let books = [
|
private static let books = [
|
||||||
"John", "Matthew", "Imitation of Christ"]
|
"John", "Matthew", "Imitation of Christ"]
|
||||||
|
|
||||||
|
/// Creates a new player with empty name and zero score
|
||||||
|
// static func new() -> Line {
|
||||||
|
// Line(id: nil, chap: 1, body: "")
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// Returns a random score
|
||||||
|
static func randomScore() -> Int {
|
||||||
|
10 * Int.random(in: 0...100)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func randomBook() -> String {
|
||||||
|
books.randomElement()!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Persistence
|
// MARK: - Persistence
|
||||||
|
|
|
@ -49,12 +49,11 @@ struct LineRequest: Queryable {
|
||||||
// This method is not required by Queryable, but it makes it easier
|
// This method is not required by Queryable, but it makes it easier
|
||||||
// to test LineRequest.
|
// to test LineRequest.
|
||||||
func fetchValue(_ db: Database) throws -> [Line] {
|
func fetchValue(_ db: Database) throws -> [Line] {
|
||||||
return try Line.filter(bookColumn == book).fetchAll(db)
|
if book == "" {
|
||||||
// if book == "" {
|
return try Line.filter(bookColumn == Line.randomBook()).fetchAll(db)
|
||||||
// return try Line.filter(bookColumn == Line.randomBook()).fetchAll(db)
|
} else {
|
||||||
// } else {
|
return try Line.filter(bookColumn == book).fetchAll(db)
|
||||||
// return try Line.filter(bookColumn == book).fetchAll(db)
|
}
|
||||||
// }
|
|
||||||
// switch ordering {
|
// switch ordering {
|
||||||
// case .byScore:
|
// case .byScore:
|
||||||
// return try Line.all().fetchAll(db)
|
// return try Line.all().fetchAll(db)
|
||||||
|
|
|
@ -40,7 +40,6 @@ extension AppDatabase {
|
||||||
// // demo purpose.
|
// // demo purpose.
|
||||||
// try appDatabase.createRandomPlayersIfEmpty()
|
// try appDatabase.createRandomPlayersIfEmpty()
|
||||||
// }
|
// }
|
||||||
print("initing database")
|
|
||||||
try appDatabase.initDatabase()
|
try appDatabase.initDatabase()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,12 +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 groupId: Int
|
|
||||||
var pos: Int
|
var pos: Int
|
||||||
var undoLevel: Int
|
|
||||||
var currentLevel: Int
|
|
||||||
var minLevel: Int
|
|
||||||
var maxLevel: Int
|
|
||||||
var title: String
|
var title: String
|
||||||
var book: String
|
var book: String
|
||||||
var scrollId: String
|
var scrollId: String
|
||||||
|
@ -32,6 +27,7 @@ struct Ribbon: Identifiable, Equatable {
|
||||||
extension Ribbon {
|
extension Ribbon {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Persistence
|
||||||
|
|
||||||
/// Make Line a Codable Record.
|
/// Make Line a Codable Record.
|
||||||
///
|
///
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue