diff --git a/Fenestra.swift b/Fenestra.swift index 1865182..0bc43f1 100644 --- a/Fenestra.swift +++ b/Fenestra.swift @@ -121,8 +121,8 @@ struct Pane: View { destRibbon: selectedRibbon[0], appDatabase: appDatabase, paneConnector: paneConnector, - refresh: $refresh, - loading: true) + loading: true, + bump: false) } .onChange(of: paneConnector.refresh) { _ in print("inside change") diff --git a/NaviBar.swift b/NaviBar.swift index 96ba3e0..7094f6e 100644 --- a/NaviBar.swift +++ b/NaviBar.swift @@ -5,28 +5,62 @@ 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 { - // goToRibbon(selectedRibbon: sr[0], - // destRibbon: ribbon, - // appDatabase: appDatabase, - // paneConnector: paneConnector, - // refresh: $refresh, - // loading: false) + 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() diff --git a/RibbonRequest.swift b/RibbonRequest.swift index 70c5854..dac7b9d 100644 --- a/RibbonRequest.swift +++ b/RibbonRequest.swift @@ -44,6 +44,7 @@ struct RibbonRequest: Queryable { // this has to be a global variable let totalLevels = 3 do { + print("back reload") if dir != nil && groupId != nil { sql = """ SELECT * FROM Ribbon \ @@ -55,7 +56,7 @@ struct RibbonRequest: Queryable { return [] } - print("back all ribbon test: \(ret)") + print("back all ribbon all: \(ret)") let currentLevel = ret[0].currentLevel let minLevel = ret[0].minLevel @@ -71,14 +72,15 @@ struct RibbonRequest: Queryable { if dir == .prev { // no back undo steps left if currentLevel == minLevel { - return [] + newCurrentLevel = currentLevel } } else if dir == .prev { // no forward redo steps left if currentLevel == maxLevel { - return [] + newCurrentLevel = maxLevel + } else { + newCurrentLevel = (currentLevel + 1) %% totalLevels } - newCurrentLevel = (currentLevel + 1) %% totalLevels } @@ -91,19 +93,32 @@ struct RibbonRequest: Queryable { """ ret = try Ribbon.fetchAll(db, sql: sql, arguments: [groupId, newCurrentLevel]) - print("back ribbon test: \(ret)") + print("back ribbon return: \(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 - """ + if groupId != nil { + let sql = """ + SELECT * from Ribbon r1 \ + WHERE r1.groupId = ? + ORDER BY undoLevel ASC + """ - var ret = try Ribbon.fetchAll(db, sql: sql) - print("xxxxx fetching ribbons") - print(ret) - return ret + 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) diff --git a/Stats.swift b/Stats.swift new file mode 100644 index 0000000..1580f4e --- /dev/null +++ b/Stats.swift @@ -0,0 +1,113 @@ +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)) + } + } + } + } +} diff --git a/gloss.xcodeproj/project.pbxproj b/gloss.xcodeproj/project.pbxproj index 1ec2536..7e80c5f 100644 --- a/gloss.xcodeproj/project.pbxproj +++ b/gloss.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 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 */; }; 8514D5BF299F04710054F185 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = 8514D5BE299F04710054F185 /* GRDB */; }; 852774C129A150B100458CA7 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852774C029A150B100458CA7 /* Line.swift */; }; @@ -51,6 +52,7 @@ 851259AF2C05281300BE70F8 /* BackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackButton.swift; sourceTree = ""; }; 851259B12C05299200BE70F8 /* ForwardArrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForwardArrow.swift; sourceTree = ""; }; 851259B52C07560800BE70F8 /* NaviBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NaviBar.swift; sourceTree = ""; }; + 851259B72C0A145500BE70F8 /* Stats.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = ""; }; 8514D5BB299EFB780054F185 /* store.db */ = {isa = PBXFileReference; lastKnownFileType = file; path = store.db; sourceTree = ""; }; 852774C029A150B100458CA7 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; 8528897429B2B86B003F2E16 /* CrownOfThorns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrownOfThorns.swift; sourceTree = ""; }; @@ -126,6 +128,7 @@ 85942EF429B108C600307621 /* Seg.swift */, 85942EF629B108EA00307621 /* SegDenormRequest.swift */, 851259B52C07560800BE70F8 /* NaviBar.swift */, + 851259B72C0A145500BE70F8 /* Stats.swift */, 85942EF829B1150B00307621 /* SegDenorm.swift */, 85942EEA29AD55A400307621 /* RibbonRequest.swift */, 85942EE329ACF54A00307621 /* ScrollableView.swift */, @@ -307,6 +310,7 @@ 85942EEF29AEA18300307621 /* SelectedRibbonRequest.swift in Sources */, 8590D96C29A92146001EF84F /* JsonImport.swift in Sources */, 85942EED29AEA04200307621 /* SelectedRibbon.swift in Sources */, + 851259B82C0A145500BE70F8 /* Stats.swift in Sources */, 85431A892905F4F500EE0760 /* glossApp.swift in Sources */, 8528897C29BD69B2003F2E16 /* VisibilityTrackingScrollView.swift in Sources */, 85942EF929B1150B00307621 /* SegDenorm.swift in Sources */, diff --git a/gloss/AppDatabase.swift b/gloss/AppDatabase.swift index a4ecdd9..1dff1f2 100644 --- a/gloss/AppDatabase.swift +++ b/gloss/AppDatabase.swift @@ -1,6 +1,10 @@ import Foundation import GRDB + + +let totalLevels = 3 + /// AppDatabase lets the application access the database. /// /// It applies the pratices recommended at @@ -122,6 +126,22 @@ func load(_ filename: String) -> T { 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 { try await dbWriter.write { [ribbon] db in @@ -202,8 +222,41 @@ extension AppDatabase { } } - func bumpRibbon(_ ribbon: inout Ribbon) async throws { - let totalLevels = 3 + 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]() @@ -211,18 +264,13 @@ extension AppDatabase { level = (level + 1) % totalLevels delLevels2.append(level) } - print("del levels") let delLevels = delLevels2 - print(delLevels) - let newMax = (ribbon.currentLevel + 1) % totalLevels + let newMax = (ribbon.currentLevel + 1) %% totalLevels let newCurrent = newMax - let newMin = newMax == ribbon.minLevel ? (ribbon.minLevel + 1) % totalLevels + let newMin = newMax == ribbon.minLevel ? (ribbon.minLevel + 1) %% totalLevels : ribbon.minLevel - print(newMin) - print(newMax) - print(newCurrent) ribbon.minLevel = newMin ribbon.maxLevel = newMax ribbon.undoLevel = newCurrent @@ -231,6 +279,7 @@ extension AppDatabase { do { try await dbWriter.write { [ribbon] db in + print("meow enter bump 1") for l in delLevels { try db.execute(sql: """ DELETE FROM Ribbon \ @@ -246,11 +295,11 @@ extension AppDatabase { // upsert - - let ret = try Ribbon.fetchAll(db, sql: """ + 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) @@ -265,20 +314,27 @@ extension AppDatabase { try updatedRibbon.update(db) } - print("ribbon inserted: \(ret)") + 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 ORDER BY groupId + SELECT * from Ribbon WHERE groupId = 1 ORDER BY undoLevel ASC """) - for r in ret2 { - print("ribbon dump: \(r)") - } - } + 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 { diff --git a/gloss/ContentView.swift b/gloss/ContentView.swift index f5baff9..ed64ed5 100644 --- a/gloss/ContentView.swift +++ b/gloss/ContentView.swift @@ -39,20 +39,45 @@ 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, destRibbon: Ribbon, appDatabase: AppDatabase, paneConnector: PaneConnector, - refresh: Binding, - loading: Bool) + loading: Bool, + bump: Bool) { + print("meow goto ribbon - selected ribbon: \(selectedRibbon), dest ribbon: \(destRibbon) ") DispatchQueue.main.asyncAfter(deadline: .now()) { Task { var scrollOffsetToSave = paneConnector.currentOffset var scrollIdToSave = paneConnector.currentId - var updatedRibbon = selectedRibbon print("go to ribbon") print("\(selectedRibbon.id) \(destRibbon.id!)") @@ -72,8 +97,6 @@ func goToRibbon(selectedRibbon: Ribbon, print("toggling") print("paneconnector: \(paneConnector.refresh)") - refresh.wrappedValue.toggle() - var updateSelectRibbon = SelectedRibbon(id: Int64(1), ribbonGroupId: Int64(destRibbon.groupId)) // print("Saving selected ribbon") // print(updateSelectRibbon) @@ -84,23 +107,26 @@ func goToRibbon(selectedRibbon: Ribbon, } } - // this gets run regardless of if we switch ribbons or not - // so if you click the same ribbon or a different ribbon - if !loading { - print("not loading") + // // this gets run regardless of if we switch ribbons or not + // // so if you click the same ribbon or a different ribbon + // if !loading || bump { + // print("not loading") - print("saving ribbon") - // updating the ribbon location - updatedRibbon.scrollOffset = Int(floor(scrollOffsetToSave)) - updatedRibbon.scrollId = scrollIdToSave - // updatedRibbon.undoLevel = updatedRibbon.undoLevel + 1 - // updatedRibbon.currentLevel = updatedRibbon.currentLevel + 1 - _ = try await appDatabase.bumpRibbon(&updatedRibbon) + // print("saving ribbon") + // // updating the ribbon location + // updatedRibbon.scrollOffset = Int(floor(scrollOffsetToSave)) + // updatedRibbon.scrollId = scrollIdToSave + // // updatedRibbon.undoLevel = updatedRibbon.undoLevel + 1 + // // updatedRibbon.currentLevel = updatedRibbon.currentLevel + 1 - } else { - print("loading") - } + // if bump { + // _ = try await appDatabase.bumpRibbon(&updatedRibbon) + // } + + // } else { + // print("loading") + // } } } @@ -125,7 +151,7 @@ struct RibbonCrown: View { @Environment(\.appDatabase) private var appDatabase - @Query(SelectedRibbonRequest()) private var sr: [Ribbon] + @Query(SelectedRibbonRequest()) private var selectedRibbon: [Ribbon] @State var saveOffset = CGFloat() @Binding var refresh: Bool @@ -157,12 +183,18 @@ struct RibbonCrown: View { } .onTapGesture { 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, appDatabase: appDatabase, paneConnector: paneConnector, - refresh: $refresh, - loading: false) + loading: false, + bump: true) } } .frame(width: CGFloat(100 * 1.66 * scale + 10), height: CGFloat(100 * scale + 5)) @@ -276,7 +308,18 @@ struct ContentView: View { .background(Color(red: 0.1, green: 0.1, blue: 0.1)) .frame(alignment: .topLeading) - NaviBar().offset(x: geometry.size.width - 300) + 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 { // Top pane @@ -392,27 +435,7 @@ struct ContentView: View { } } } - func handleVisibilityChanged2(_: String, change _: VisibilityChange, tracker _: VisibilityTracker) {} - - func handleVisibilityChanged(_: String, change _: VisibilityChange, tracker: VisibilityTracker) { - // 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 = {