diff --git a/RibbonGroup.swift b/RibbonGroup.swift new file mode 100644 index 0000000..bce189e --- /dev/null +++ b/RibbonGroup.swift @@ -0,0 +1,59 @@ +// +// RibbonGroup.swift +// gloss +// +// Created by Saint on 2/24/23. +// + +import GRDB +/// The Line struct. +/// +/// Identifiable conformance supports SwiftUI list animations, and type-safe +/// GRDB primary key methods. +/// Equatable conformance supports tests. +struct RibbonGroup: 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 pos: Int + var title: String + var current_undo_level: Int + var min_level: Int + var max_level: Int + +} + +extension RibbonGroup { +} + +// MARK: - Persistence + +/// Make Line a Codable Record. +/// +/// See +extension RibbonGroup: Codable, FetchableRecord, MutablePersistableRecord { + // Define database columns from CodingKeys + fileprivate enum Columns { + static let id = Column(CodingKeys.id) + static let pos = Column(CodingKeys.pos) + static let book = Column(CodingKeys.book) + static let title = Column(CodingKeys.title) + static let scrollOffset = Column(CodingKeys.scrollOffset) + } + + /// Updates a player id after it has been inserted in the database. + mutating func didInsert(_ inserted: InsertionSuccess) { + id = inserted.rowID + } +} + +// MARK: - Line Database Requests + +/// Define some player requests used by the application. +/// +/// See +/// See +extension DerivableRequest { +} diff --git a/SegmentedSelector.swift b/SegmentedSelector.swift new file mode 100644 index 0000000..e0d10a7 --- /dev/null +++ b/SegmentedSelector.swift @@ -0,0 +1,26 @@ +@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 + } + } + } +} diff --git a/SelectedRibbon.swift b/SelectedRibbon.swift index 67e1a65..c21073c 100644 --- a/SelectedRibbon.swift +++ b/SelectedRibbon.swift @@ -17,7 +17,7 @@ struct SelectedRibbon: Identifiable, Equatable { /// 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 ribbonId: Int64 + var ribbonGroupId: Int64 } extension SelectedRibbon { @@ -34,7 +34,7 @@ extension SelectedRibbon: Codable, FetchableRecord, MutablePersistableRecord { static let id = Column(CodingKeys.id) static let ribbonId = Column(CodingKeys.ribbonId) } - + /// Updates a player id after it has been inserted in the database. mutating func didInsert(_ inserted: InsertionSuccess) { id = inserted.rowID diff --git a/gloss.xcodeproj/project.pbxproj b/gloss.xcodeproj/project.pbxproj index fd3256a..1adcab0 100644 --- a/gloss.xcodeproj/project.pbxproj +++ b/gloss.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* 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 */; }; + 851259B42C05788800BE70F8 /* RibbonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851259B32C05788800BE70F8 /* RibbonGroup.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 */; }; @@ -49,6 +50,7 @@ /* Begin PBXFileReference section */ 851259AF2C05281300BE70F8 /* BackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackButton.swift; sourceTree = ""; }; 851259B12C05299200BE70F8 /* ForwardArrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForwardArrow.swift; sourceTree = ""; }; + 851259B32C05788800BE70F8 /* RibbonGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RibbonGroup.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 = ""; }; @@ -129,6 +131,7 @@ 8528897B29BD69B2003F2E16 /* VisibilityTracker.swift */, 8528897A29BD69B1003F2E16 /* VisibilityTrackingModifier.swift */, 8528897929BD69B1003F2E16 /* VisibilityTrackingScrollView.swift */, + 851259B32C05788800BE70F8 /* RibbonGroup.swift */, 8590D96A29A8374B001EF84F /* json */, 8514D5BA299EF2EC0054F185 /* db */, 85F01DF9297878B400F317B4 /* fonts */, @@ -301,6 +304,7 @@ 8590D96729A183EE001EF84F /* AppDatabase.swift in Sources */, 8590D96929A18A6D001EF84F /* LineRequest.swift in Sources */, 852774C129A150B100458CA7 /* Line.swift in Sources */, + 851259B42C05788800BE70F8 /* RibbonGroup.swift in Sources */, 85942EEF29AEA18300307621 /* SelectedRibbonRequest.swift in Sources */, 8590D96C29A92146001EF84F /* JsonImport.swift in Sources */, 85942EED29AEA04200307621 /* SelectedRibbon.swift in Sources */, diff --git a/gloss/AppDatabase.swift b/gloss/AppDatabase.swift index b0b3aa1..c7b2061 100644 --- a/gloss/AppDatabase.swift +++ b/gloss/AppDatabase.swift @@ -51,10 +51,19 @@ struct AppDatabase { t.column("book", .text).notNull() } - try db.create(table: "Ribbon") { t in + try db.create(table: "RibbonGroup") { t in t.autoIncrementedPrimaryKey("id") + t.column("currentUndoLevel", .integer).notNull() + t.column("minLevel", .integer).notNull() + t.column("maxLevel", .text).notNull() t.column("pos", .integer).notNull() t.column("title", .text).notNull() + } + + try db.create(table: "Ribbon") { t in + t.autoIncrementedPrimaryKey("id") + t.column("group", .integer).notNull() + t.column("undoLevel", .integer).notNull() t.column("book", .text).notNull() t.column("scrollOffset", .integer).notNull() t.column("scrollId", .text) @@ -62,7 +71,7 @@ struct AppDatabase { try db.create(table: "SelectedRibbon") { t in t.autoIncrementedPrimaryKey("id") - t.column("ribbonId", .integer).notNull() + t.column("ribbonGroupId", .integer).notNull() } try db.create(table: "ScrollState") { t in @@ -246,10 +255,50 @@ extension AppDatabase { if try Line.all().isEmpty(db) { try importJson("john_export.json", db) try importJson("mark_export.json", db) - _ = try Ribbon(id: 1, pos: 1, title: "John", book: "bible.john", scrollId: "1", scrollOffset: 0).inserted(db) - _ = try Ribbon(id: 2, pos: 2, title: "Gospel of Mark", book: "bible.mark", scrollId: "1", scrollOffset: 300).inserted(db) - _ = try Ribbon(id: 3, pos: 3, title: "John 2", book: "bible.john", scrollId: "1", scrollOffset: 0).inserted(db) - _ = try SelectedRibbon(id: 1, ribbonId: 1).inserted(db) + + _ = try RibbonGroup(id: 1, + pos: 1, + title: "John", + current_undo_level: 1, + min_level: 1, + max_level: 1).inserted(db) + + _ = try Ribbon(id: 1, + group: 1, + undoLevel: 1, + book: "bible.john", + scrollId: "1", + scrollOffset: 0).inserted(db) + + _ = try RibbonGroup(id: 2, + pos: 2, + title: "Second", + current_undo_level: 1, + min_level: 1, + max_level: 1).inserted(db) + + _ = try Ribbon(id: 2, + group: 2, + undoLevel: 1, + book: "bible.mark", + scrollId: "1", + scrollOffset: 0).inserted(db) + + _ = try RibbonGroup(id: 3, + pos: 3, + title: "Another one", + current_undo_level: 1, + min_level: 1, + max_level: 1).inserted(db) + + _ = try Ribbon(id: 3, + group: 3, + undoLevel: 1, + book: "bible.john", + scrollId: "1", + scrollOffset: 0).inserted(db) + + _ = try SelectedRibbon(id: 1, ribbonGroupId: 1).inserted(db) } } } catch { diff --git a/gloss/ContentView.swift b/gloss/ContentView.swift index f9c5d59..98c93fc 100644 --- a/gloss/ContentView.swift +++ b/gloss/ContentView.swift @@ -272,46 +272,14 @@ struct ContentView: View { HStack { BackArrow() .frame(width: CGFloat(30), height: CGFloat(30)) - .scaledToFit() + .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))) - .tag(0) 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))) - .tag(1) - - Text("cat") - .foregroundColor(Color(UIColor(red: 0.30, green: 0.30, blue: 0.30, alpha: 0.4))) - .tag(2) } - .cornerRadius(15) - - 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.2)) { - 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.2)) { - self.selection = 1 - } - } - } - - .background(Color.black) .cornerRadius(5) } .offset(x: geometry.size.width - 300) diff --git a/gloss/Ribbon.swift b/gloss/Ribbon.swift index 9957e71..fda5c1d 100644 --- a/gloss/Ribbon.swift +++ b/gloss/Ribbon.swift @@ -17,8 +17,8 @@ struct Ribbon: Identifiable, Equatable { /// 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 pos: Int - var title: String + var group: Int + var undoLevel: Int var book: String var scrollId: String var scrollOffset: Int @@ -41,7 +41,7 @@ extension Ribbon: Codable, FetchableRecord, MutablePersistableRecord { static let title = Column(CodingKeys.title) static let scrollOffset = Column(CodingKeys.scrollOffset) } - + /// Updates a player id after it has been inserted in the database. mutating func didInsert(_ inserted: InsertionSuccess) { id = inserted.rowID