sort of workoing

undo
Saint 2023-02-28 17:03:58 -05:00
parent de0a17fc9b
commit 65563f84fc
8 changed files with 343 additions and 77 deletions

View File

@ -15,6 +15,8 @@ import GRDBQuery
/// }
/// }
var idColumn = Column("id")
struct RibbonRequest: Queryable {
// enum Ordering {
// case byScore
@ -23,7 +25,7 @@ struct RibbonRequest: Queryable {
/// The ordering used by the player request.
// var ordering: Ordering
// var book: String
var id: Int64!
// MARK: - Queryable Implementation
@ -47,7 +49,11 @@ struct RibbonRequest: Queryable {
// This method is not required by Queryable, but it makes it easier
func fetchValue(_ db: Database) throws -> [Ribbon] {
return try Ribbon.fetchAll(db)
if (id == nil) {
return try Ribbon.fetchAll(db)
} else {
return try Ribbon.filter(idColumn == id).fetchAll(db)
}
// if book == "" {
// return try Ribbon.filter(bookColumn == Ribbon.randomBook()).fetchAll(db)

51
SelectedRibbon.swift Normal file
View File

@ -0,0 +1,51 @@
//
// Ribbon.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 SelectedRibbon: 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 ribbonId: Int64
}
extension SelectedRibbon {
}
// MARK: - Persistence
/// Make Line a Codable Record.
///
/// See <https://github.com/groue/GRDB.swift/blob/master/README.md#records>
extension SelectedRibbon: Codable, FetchableRecord, MutablePersistableRecord {
// Define database columns from CodingKeys
fileprivate enum Columns {
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
}
}
// MARK: - Line Database Requests
/// Define some player requests used by the application.
///
/// See <https://github.com/groue/GRDB.swift/blob/master/README.md#requests>
/// See <https://github.com/groue/GRDB.swift/blob/master/Documentation/GoodPracticesForDesigningRecordTypes.md>
extension DerivableRequest<SelectedRibbon> {
}

View File

@ -0,0 +1,68 @@
import Combine
import GRDB
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(SelectedRibbonRequest(ordering: .byName)) private var players: [SelectedRibbon]
///
/// var body: some View {
/// List(players) { player in ... )
/// }
/// }
struct SelectedRibbonRequest: Queryable {
// enum Ordering {
// case byScore
// case byName
// }
/// The ordering used by the player request.
// var ordering: Ordering
var id: Int64!
// MARK: - Queryable Implementation
static var defaultValue: [SelectedRibbon] { [] }
func publisher(in appDatabase: AppDatabase) -> AnyPublisher<[SelectedRibbon], Error> {
// Build the publisher from the general-purpose read-only access
// granted by `appDatabase.reader`.
// Some apps will prefer to call a dedicated method of `appDatabase`.
ValueObservation
.tracking(fetchValue(_:))
.publisher(
in: appDatabase.reader,
// The `.immediate` scheduling feeds the view right on
// subscription, and avoids an undesired animation when the
// application starts.
scheduling: .immediate)
.eraseToAnyPublisher()
}
// This method is not required by Queryable, but it makes it easier
func fetchValue(_ db: Database) throws -> [SelectedRibbon] {
if (id == nil) {
return try SelectedRibbon.fetchAll(db)
} else {
return try SelectedRibbon.filter(idColumn == id).fetchAll(db)
}
// if book == "" {
// return try SelectedRibbon.filter(bookColumn == SelectedRibbon.randomBook()).fetchAll(db)
// } else {
// return try SelectedRibbon.filter(bookColumn == book).fetchAll(db)
// }
// switch ordering {
// case .byScore:
// return try SelectedRibbon.all().fetchAll(db)
// case .byName:
// // return try SelectedRibbon.all().orderedByName().fetchAll(db)
// return try SelectedRibbon.all().fetchAll(db)
// }
}
}

View File

@ -27,6 +27,8 @@
85942EE729AD083600307621 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 85942EE629AD083600307621 /* Introspect */; };
85942EE929AD51A100307621 /* Ribbon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85942EE829AD51A100307621 /* Ribbon.swift */; };
85942EEB29AD55A400307621 /* RibbonRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85942EEA29AD55A400307621 /* RibbonRequest.swift */; };
85942EED29AEA04200307621 /* SelectedRibbon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85942EEC29AEA04200307621 /* SelectedRibbon.swift */; };
85942EEF29AEA18300307621 /* SelectedRibbonRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85942EEE29AEA18300307621 /* SelectedRibbonRequest.swift */; };
85F01DF82978787800F317B4 /* AveriaSerifLibre-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 85F01DF72978787800F317B4 /* AveriaSerifLibre-Regular.ttf */; };
85F01DFB2978790400F317B4 /* xe-Dogma-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 85F01DFA2978790400F317B4 /* xe-Dogma-Bold.ttf */; };
/* End PBXBuildFile section */
@ -50,6 +52,8 @@
85942EE329ACF54A00307621 /* ScrollableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollableView.swift; sourceTree = "<group>"; };
85942EE829AD51A100307621 /* Ribbon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ribbon.swift; sourceTree = "<group>"; };
85942EEA29AD55A400307621 /* RibbonRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RibbonRequest.swift; sourceTree = "<group>"; };
85942EEC29AEA04200307621 /* SelectedRibbon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedRibbon.swift; sourceTree = "<group>"; };
85942EEE29AEA18300307621 /* SelectedRibbonRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedRibbonRequest.swift; sourceTree = "<group>"; };
85F01DF72978787800F317B4 /* AveriaSerifLibre-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "AveriaSerifLibre-Regular.ttf"; sourceTree = "<group>"; };
85F01DFA2978790400F317B4 /* xe-Dogma-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "xe-Dogma-Bold.ttf"; sourceTree = "<group>"; };
85F01DFC29787B3500F317B4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
@ -83,6 +87,8 @@
85431A7C2905F4F500EE0760 = {
isa = PBXGroup;
children = (
85942EEC29AEA04200307621 /* SelectedRibbon.swift */,
85942EEE29AEA18300307621 /* SelectedRibbonRequest.swift */,
85942EEA29AD55A400307621 /* RibbonRequest.swift */,
85942EE329ACF54A00307621 /* ScrollableView.swift */,
8590D96A29A8374B001EF84F /* json */,
@ -251,7 +257,9 @@
8590D96929A18A6D001EF84F /* LineRequest.swift in Sources */,
8590D96E29A927CF001EF84F /* Seg.swift in Sources */,
852774C129A150B100458CA7 /* Line.swift in Sources */,
85942EEF29AEA18300307621 /* SelectedRibbonRequest.swift in Sources */,
8590D96C29A92146001EF84F /* JsonImport.swift in Sources */,
85942EED29AEA04200307621 /* SelectedRibbon.swift in Sources */,
85431A892905F4F500EE0760 /* glossApp.swift in Sources */,
85431A9C2905F5D800EE0760 /* SwiftUIView.swift in Sources */,
85942EE429ACF54A00307621 /* ScrollableView.swift in Sources */,

View File

@ -48,6 +48,11 @@ struct AppDatabase {
t.column("book", .text).notNull()
t.column("scrollOffset", .integer).notNull()
}
try db.create(table: "SelectedRibbon") { t in
t.autoIncrementedPrimaryKey("id")
t.column("ribbonId", .integer).notNull()
}
}
@ -87,6 +92,24 @@ func load<T: Decodable>(_ filename: String) -> T {
extension AppDatabase {
func saveRibbon(_ ribbon: inout Ribbon) async throws {
// if ribbon.name.isEmpty {
// throw ValidationError.missingName
// }
ribbon = try await dbWriter.write { [ribbon] db in
try ribbon.saved(db)
}
}
func saveSelectedRibbon(_ selectedRibbon: inout SelectedRibbon) async throws {
// if selectedRibbon.name.isEmpty {
// throw ValidationError.missingName
// }
selectedRibbon = try await dbWriter.write { [selectedRibbon] db in
try selectedRibbon.saved(db)
}
}
/// Create random Lines if the database is empty.
func createRandomLinesIfEmpty() throws {
@ -103,6 +126,7 @@ extension AppDatabase {
// try createRandomLines(db)
_ = try Ribbon(id: nil, book: "bible.john", scrollOffset: 0).inserted(db)
_ = try Ribbon(id: nil, book: "bible.john", scrollOffset: 2000).inserted(db)
_ = try SelectedRibbon(id: 1, ribbonId: 1).inserted(db)
}
}
}
@ -135,7 +159,7 @@ extension AppDatabase {
// MARK: - Database Access: Reads
// This demo app does not provide any specific reading method, and instead
// This demo app does not provide any specific reading method, and insteadKK
// gives an unrestricted read-only access to the rest of the application.
// In your app, you are free to choose another path, and define focused
// reading methods.

View File

@ -14,6 +14,25 @@ let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "network
// var curBook = "John"
extension UserDefaults {
public func optionalInt(forKey defaultName: String) -> Int? {
let defaults = self
if let value = defaults.value(forKey: defaultName) {
return value as? Int
}
return nil
}
public func optionalBool(forKey defaultName: String) -> Bool? {
let defaults = self
if let value = defaults.value(forKey: defaultName) {
return value as? Bool
}
return nil
}
}
extension UINavigationController {
override open func viewDidLoad() {
super.viewDidLoad()
@ -46,23 +65,132 @@ struct BlueButtonStyle: ButtonStyle {
}
}
struct SwitchButton : View {
var ribbon: Ribbon
@Binding var selectedRibbon : Ribbon?
@Binding var book : String
@Binding var scrollOffset : CGFloat
struct PositionObservingView<Content: View>: View {
var coordinateSpace: CoordinateSpace
@Binding var position: CGPoint
@ViewBuilder var content: () -> Content
var body: some View {
Button("meow") {
book = ribbon.book
selectedRibbon = ribbon
Print(ribbon.scrollOffset)
Print(scrollOffset)
scrollOffset = CGFloat(ribbon.scrollOffset)
//Print("hellosdf dddd")
content()
.background(GeometryReader { geometry in
Color.clear.preference(
key: PreferenceKey.self,
value: geometry.frame(in: coordinateSpace).origin
)
})
.onPreferenceChange(PreferenceKey.self) { position in
self.position = position
// Print(self.position)
}
}
}
private extension PositionObservingView {
struct PreferenceKey: SwiftUI.PreferenceKey {
static var defaultValue: CGPoint { .zero }
static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
// No-op
}
.buttonStyle(BlueButtonStyle())
}
}
struct OffsetObservingScrollView<Content: View>: View {
var axes: Axis.Set = [.vertical]
var showsIndicators = true
@Binding var offset: CGPoint
@ViewBuilder var content: () -> Content
// The name of our coordinate space doesn't have to be
// stable between view updates (it just needs to be
// consistent within this view), so we'll simply use a
// plain UUID for it:
private let coordinateSpaceName = UUID()
var body: some View {
ScrollView(axes, showsIndicators: showsIndicators) {
PositionObservingView(
coordinateSpace: .named(coordinateSpaceName),
position: Binding(
get: { offset },
set: { newOffset in
offset = CGPoint(
x: -newOffset.x,
y: -newOffset.y
)
}
),
content: content
)
}
.coordinateSpace(name: coordinateSpaceName)
}
}
struct SwitchButton : View {
@State var ribbon: Ribbon
// @State var selectedRibbon: SelectedRibbon
@Binding var book : String
@Binding var scrollOffset : CGFloat
@Binding var readOffset: CGPoint
@Environment(\.appDatabase) private var appDatabase
@Query(SelectedRibbonRequest()) private var sr: [SelectedRibbon]
@State var saveOffset = CGFloat()
var body: some View {
// ForEach(sr) { selectedRibbon in
Button("meow",
action: {
Task {
var selectedRibbon = sr[0]
saveOffset = CGFloat(readOffset.y)
Print("save/read offset", readOffset.y)
Print("START")
_ = Print(ribbon)
_ = Print(selectedRibbon)
Print("START2")
if (selectedRibbon.ribbonId != ribbon.id!) {
Print(ribbon.id!)
Print("switching")
book = ribbon.book
scrollOffset = CGFloat(ribbon.scrollOffset)
// scrollOffset = CGFloat(1500)
Print("setted offset value", scrollOffset)
selectedRibbon.ribbonId = ribbon.id!
_ = try await appDatabase.saveSelectedRibbon(&selectedRibbon)
_ = Print(selectedRibbon)
}
var editedRibbon = ribbon
editedRibbon.scrollOffset = Int(saveOffset)
Print("current ribbon offset after potential switch", editedRibbon.scrollOffset)
_ = try await appDatabase.saveRibbon(&editedRibbon)
_ = Print(editedRibbon)
Print("ribbon offset saved")
Print("set offset value", scrollOffset)
Print("read offset value", readOffset.y)
Print("END")
_ = Print(ribbon)
_ = Print(selectedRibbon)
Print("END2")
}
}
)
.buttonStyle(BlueButtonStyle())
// }
}
}
@ -75,32 +203,47 @@ struct ContentView: View {
// @State var scrollTo1 : Int64?
@State var selectedLine : Int64?
@State var scrollOffset = CGFloat()
@State var selectedRibbon: Ribbon!
// @State var selectedRibbon: Ribbon!,
// @State var selectedRibbon: Ribbon!
// @State var selectedRibbonId = Int64(UserDefaults.standard.optionalInt(forKey: "selectedRibbonId") ?? 1)
@Query(SelectedRibbonRequest()) private var selectedRibbon: [SelectedRibbon]
@State var endedDrag = true
@State var readOffset = CGPoint()
@Query(LineRequest(ordering: .byScore, book: "bible.john")) private var lines: [Line]
@Query(RibbonRequest()) private var ribbons: [Ribbon]
// @Query<LineRequest> private var lines: [Line]
// @Query*RibbonRequest> private var selectedRibbon: [Ribbon]
// @Query(RibbonRequest(id: Int64(UserDefaults.standard.optionalInt(forKey: "lastRibbonId") ?? 1))) private var selectedRibbon: [Ribbon]
init() {
UITableView.appearance().backgroundColor = UIColor(Color(red: 0.2, green: 0.2, blue: 0.2))
// _lines = Query(LineRequest(ordering: .byScore, book: curBook))
// _selectedRibbon = Query(RibbonRequest(id: Int64(UserDefaults.standard.optionalInt(forKey: "lastRibbonId") ?? 1)))
}
// @Environment(\.managedObjectContext) private var viewContext
var body: some View {
GeometryReader { geometry in
ZStack{
VStack{
ForEach(ribbons) { ribbon in
SwitchButton(ribbon: ribbon,
selectedRibbon: $selectedRibbon,
book: $lines.book,
scrollOffset: $scrollOffset)
.buttonStyle(BlueButtonStyle())
ForEach(selectedRibbon) { sr in
SwitchButton(ribbon: ribbon,
// selectedRibbon:sr,
book: $lines.book,
scrollOffset: $scrollOffset,
readOffset: $readOffset
)
.buttonStyle(BlueButtonStyle())
}
}
}
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
@ -109,7 +252,8 @@ struct ContentView: View {
// VStack (spacing: 0){
ScrollViewReader { proxy in
//ScrollableView($offset, animationDuration: 0) {
ScrollView {
OffsetObservingScrollView(offset: $readOffset)
{
// List {
LazyVStack {
ForEach(lines) { line in
@ -143,7 +287,10 @@ struct ContentView: View {
.introspectScrollView { scrollView in
//let width = scrollView.contentSize.width - scrollView.frame.width
//Print(scrollView.contentOffset.x)
scrollView.contentOffset.y = scrollOffset
// Print("here")
if (scrollOffset != scrollView.contentOffset.y) {
scrollView.contentOffset.y = scrollOffset
}
}
.listStyle(PlainListStyle())
@ -154,15 +301,15 @@ struct ContentView: View {
.offset(x:30 , y:0)
.offset(x: pulledOut.width)
.offset(x: viewState.width, y: viewState.height)
.onAppear {
if (selectedRibbon != nil) {
Print(selectedRibbon)
//scrollOffset.y = scrollOffset
}
}
.gesture(
DragGesture()
.onChanged { gesture in
if (endedDrag) {
endedDrag = false
scrollOffset = readOffset.y - 20
_ = Print("meow")
}
// logger.error("hello222")
// NSLog("hellooo")
//Print(viewState.width)
@ -171,6 +318,7 @@ struct ContentView: View {
// logger.log("hello")
}
.onEnded { _ in
endedDrag = true
var pulledOutWidth = CGFloat(0)
if (viewState.width < 0) {
pulledOutWidth = CGFloat(0)

View File

@ -49,44 +49,5 @@ extension Ribbon: Codable, FetchableRecord, MutablePersistableRecord {
///
/// See <https://github.com/groue/GRDB.swift/blob/master/README.md#requests>
/// See <https://github.com/groue/GRDB.swift/blob/master/Documentation/GoodPracticesForDesigningRecordTypes.md>
extension DerivableRequest<Line> {
/// A request of players ordered by name.
///
/// For example:
///
/// let players: [Line] = try dbWriter.read { db in
/// try Line.all().orderedByName().fetchAll(db)
/// }
//func orderedByName() -> Self {
// // Sort by name in a localized case insensitive fashion
// // See https://github.com/groue/GRDB.swift/blob/master/README.md#string-comparison
// order(Line.Columns.name.collating(.localizedCaseInsensitiveCompare))
//}
///// A request of players ordered by score.
/////
///// For example:
/////
///// let players: [Line] = try dbWriter.read { db in
///// try Line.all().orderedByScore().fetchAll(db)
///// }
///// let bestLine: Line? = try dbWriter.read { db in
///// try Line.all().orderedByScore().fetchOne(db)
///// }
//func orderedByScore() -> Self {
// // Sort by descending score, and then by name, in a
// // localized case insensitive fashion
// // See https://github.com/groue/GRDB.swift/blob/master/README.md#string-comparison
// order(
// Line.Columns.score.desc,
// Line.Columns.name.collating(.localizedCaseInsensitiveCompare))
//}
extension DerivableRequest<Ribbon> {
}
// Ribbon.swift
// gloss
//
// Created by Saint on 2/27/23.
//
import Foundation