builds, still working on undo

undo
saint 2024-05-29 16:02:08 -04:00
parent 168a057a2a
commit 19ca7be678
5 changed files with 157 additions and 69 deletions

40
NaviBar.swift Normal file
View File

@ -0,0 +1,40 @@
import GRDB
import GRDBQuery
import Foundation
import SwiftUI
struct NaviBar: View {
@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 {
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 {
// goToRibbon(selectedRibbon: sr[0],
// destRibbon: ribbon,
// appDatabase: appDatabase,
// paneConnector: paneConnector,
// refresh: $refresh,
// loading: false)
}
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)
}
}
}

View File

@ -2,30 +2,18 @@ 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 Ordering { enum UndoDir {
// case byScore case prev
// case byName case next
// } }
/// 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
@ -50,17 +38,73 @@ 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] {
var sql = """ var ret: [Ribbon]
var sql: String
// this has to be a global variable
let totalLevels = 3
do {
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 test: \(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 {
return []
}
} else if dir == .prev {
// no forward redo steps left
if currentLevel == maxLevel {
return []
}
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 test: \(ret)")
return ret
} else {
let sql = """
select distinct r1.* from Ribbon r1 join Ribbon r2 ON \ select distinct r1.* from Ribbon r1 join Ribbon r2 ON \
r1.undoLevel = r2.currentLevel AND r1.id = r2.id ORDER BY pos ASC r1.undoLevel = r2.currentLevel AND r1.id = r2.id ORDER BY pos ASC
""" """
do {
var ret = try Ribbon.fetchAll(db, sql: sql) var ret = try Ribbon.fetchAll(db, sql: sql)
print("xxxxx fetching ribbons") print("xxxxx fetching ribbons")
print(ret) print(ret)
return ret return ret
}
} catch { } catch {
print(error.localizedDescription) print(error.localizedDescription)
print(error) print(error)
@ -68,11 +112,12 @@ struct RibbonRequest: Queryable {
return [] return []
} }
if id == nil { // if id == nil {
return try Ribbon.order(Column("pos")).fetchAll(db) // return try Ribbon.order(Column("pos")).fetchAll(db)
} else { // } else {
return try Ribbon.filter(idColumn == id).fetchAll(db) // 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)
@ -88,3 +133,14 @@ struct RibbonRequest: Queryable {
// } // }
} }
} }
infix operator %%
extension Int {
static func %% (_ left: Int, _ right: Int) -> Int {
let mod = left % right
return mod >= 0 ? mod : mod + right
}
}

View File

@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
851259B02C05281300BE70F8 /* BackButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259AF2C05281300BE70F8 /* BackButton.swift */; }; 851259B02C05281300BE70F8 /* BackButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259AF2C05281300BE70F8 /* BackButton.swift */; };
851259B22C05299200BE70F8 /* ForwardArrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259B12C05299200BE70F8 /* ForwardArrow.swift */; }; 851259B22C05299200BE70F8 /* ForwardArrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259B12C05299200BE70F8 /* ForwardArrow.swift */; };
851259B62C07560800BE70F8 /* NaviBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259B52C07560800BE70F8 /* NaviBar.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,6 +50,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
851259AF2C05281300BE70F8 /* BackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackButton.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; };
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>"; };
@ -123,6 +125,7 @@
85942EEE29AEA18300307621 /* SelectedRibbonRequest.swift */, 85942EEE29AEA18300307621 /* SelectedRibbonRequest.swift */,
85942EF429B108C600307621 /* Seg.swift */, 85942EF429B108C600307621 /* Seg.swift */,
85942EF629B108EA00307621 /* SegDenormRequest.swift */, 85942EF629B108EA00307621 /* SegDenormRequest.swift */,
851259B52C07560800BE70F8 /* NaviBar.swift */,
85942EF829B1150B00307621 /* SegDenorm.swift */, 85942EF829B1150B00307621 /* SegDenorm.swift */,
85942EEA29AD55A400307621 /* RibbonRequest.swift */, 85942EEA29AD55A400307621 /* RibbonRequest.swift */,
85942EE329ACF54A00307621 /* ScrollableView.swift */, 85942EE329ACF54A00307621 /* ScrollableView.swift */,
@ -311,6 +314,7 @@
851259B22C05299200BE70F8 /* ForwardArrow.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 */,
); );

View File

@ -79,7 +79,7 @@ struct AppDatabase {
} }
// change this to nuke/remake the database // change this to nuke/remake the database
try db.create(table: "foo3") { 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()
} }
@ -215,9 +215,9 @@ extension AppDatabase {
let delLevels = delLevels2 let delLevels = delLevels2
print(delLevels) print(delLevels)
let newMax = (ribbon.currentLevel + 1) % totalLevels + 1 let newMax = (ribbon.currentLevel + 1) % totalLevels
let newCurrent = newMax let newCurrent = newMax
let newMin = newMax == ribbon.minLevel ? (ribbon.minLevel + 1) % totalLevels + 1 let newMin = newMax == ribbon.minLevel ? (ribbon.minLevel + 1) % totalLevels
: ribbon.minLevel : ribbon.minLevel
print(newMin) print(newMin)
@ -336,10 +336,10 @@ extension AppDatabase {
_ = try Ribbon(id: 1, _ = try Ribbon(id: 1,
groupId: 1, groupId: 1,
pos: 1, pos: 1,
undoLevel: 1, undoLevel: 0,
currentLevel: 1, currentLevel: 0,
minLevel: 1, minLevel: 0,
maxLevel: 1, maxLevel: 0,
title: "John", title: "John",
book: "bible.john", book: "bible.john",
scrollId: "1", scrollId: "1",
@ -347,10 +347,10 @@ extension AppDatabase {
_ = try Ribbon(id: 2, _ = try Ribbon(id: 2,
groupId: 2, groupId: 2,
pos: 2, pos: 2,
undoLevel: 1, undoLevel: 0,
currentLevel: 1, currentLevel: 0,
minLevel: 1, minLevel: 0,
maxLevel: 1, maxLevel: 0,
title: "Gospel of Mark", title: "Gospel of Mark",
book: "bible.mark", book: "bible.mark",
scrollId: "1", scrollId: "1",
@ -361,10 +361,10 @@ extension AppDatabase {
_ = try Ribbon(id: 3, _ = try Ribbon(id: 3,
groupId: 3, groupId: 3,
pos: 3, pos: 3,
undoLevel: 1, undoLevel: 0,
currentLevel: 3, currentLevel: 2,
minLevel: 1, minLevel: 0,
maxLevel: 3, maxLevel: 2,
title: "bottom", title: "bottom",
book: "bible.john", book: "bible.john",
scrollId: "1", scrollId: "1",
@ -373,10 +373,10 @@ extension AppDatabase {
_ = try Ribbon(id: 4, _ = try Ribbon(id: 4,
groupId: 3, groupId: 3,
pos: 3, pos: 3,
undoLevel: 2, undoLevel: 1,
currentLevel: 3, currentLevel: 2,
minLevel: 1, minLevel: 0,
maxLevel: 3, maxLevel: 2,
title: "topp", title: "topp",
book: "bible.john", book: "bible.john",
scrollId: "1", scrollId: "1",
@ -385,10 +385,10 @@ extension AppDatabase {
_ = try Ribbon(id: 5, _ = try Ribbon(id: 5,
groupId: 3, groupId: 3,
pos: 3, pos: 3,
undoLevel: 3, undoLevel: 2,
currentLevel: 3, currentLevel: 2,
minLevel: 1, minLevel: 0,
maxLevel: 3, maxLevel: 2,
title: "topp", title: "topp",
book: "bible.john", book: "bible.john",
scrollId: "1", scrollId: "1",

View File

@ -89,6 +89,8 @@ func goToRibbon(selectedRibbon: Ribbon,
if !loading { if !loading {
print("not loading") print("not loading")
print("saving ribbon")
// updating the ribbon location // updating the ribbon location
updatedRibbon.scrollOffset = Int(floor(scrollOffsetToSave)) updatedRibbon.scrollOffset = Int(floor(scrollOffsetToSave))
updatedRibbon.scrollId = scrollIdToSave updatedRibbon.scrollId = scrollIdToSave
@ -274,21 +276,7 @@ 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 { NaviBar().offset(x: geometry.size.width - 300)
HStack {
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)))
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)
}
.offset(x: geometry.size.width - 300)
VStack { VStack {
// Top pane // Top pane