Made Console and Game name Mandatory. Implemented currently all game details with import&export

This commit is contained in:
2021-05-20 15:57:25 +02:00
parent 5d1be37b48
commit 6c12883cb3
11 changed files with 61 additions and 35 deletions

View File

@@ -19,7 +19,7 @@ extension Console {
@NSManaged public var generation: Int64 @NSManaged public var generation: Int64
@NSManaged public var manufacturer: String? @NSManaged public var manufacturer: String?
@NSManaged public var name: String? @NSManaged public var name: String
@NSManaged public var shortName: String? @NSManaged public var shortName: String?
@NSManaged public var uuid: UUID @NSManaged public var uuid: UUID
@NSManaged public var accessories: NSSet? @NSManaged public var accessories: NSSet?

View File

@@ -49,6 +49,7 @@ extension Game : Encodable {
case createdAt case createdAt
case publisher case publisher
case isFinished case isFinished
case finishedDate
case inWishlist case inWishlist
case console case console
case cover_icloud_path case cover_icloud_path
@@ -67,6 +68,7 @@ extension Game : Encodable {
try container.encode(pickupDescription ?? "", forKey: .pickupDescription) try container.encode(pickupDescription ?? "", forKey: .pickupDescription)
try container.encode(publisher ?? "", forKey: .publisher) try container.encode(publisher ?? "", forKey: .publisher)
try container.encode(isFinished, forKey: .isFinished) try container.encode(isFinished, forKey: .isFinished)
try container.encode(finishedDate, forKey: .finishedDate)
try container.encode(inWishlist, forKey: .inWishlist) try container.encode(inWishlist, forKey: .inWishlist)
try container.encode(cover_icloud_path ?? "", forKey: .cover_icloud_path) try container.encode(cover_icloud_path ?? "", forKey: .cover_icloud_path)

View File

@@ -23,8 +23,9 @@ extension Game {
@NSManaged public var inWishlist: Bool @NSManaged public var inWishlist: Bool
@NSManaged public var isDigital: Bool @NSManaged public var isDigital: Bool
@NSManaged public var isFinished: Bool @NSManaged public var isFinished: Bool
@NSManaged public var finishedDate : Date?
@NSManaged public var lentTo: String? @NSManaged public var lentTo: String?
@NSManaged public var name: String? @NSManaged public var name: String
@NSManaged public var notes: String? @NSManaged public var notes: String?
@NSManaged public var publisher: String? @NSManaged public var publisher: String?
@NSManaged public var uuid: UUID @NSManaged public var uuid: UUID

View File

@@ -71,13 +71,15 @@ class LibraryImport {
private func makeCDGame(from game: BHLGame, _ gameDict: inout [UUID : Game], _ cdConsole: Console) { private func makeCDGame(from game: BHLGame, _ gameDict: inout [UUID : Game], _ cdConsole: Console) {
let cdGame = Game(context: CDManager.shared.viewContext) let cdGame = Game(context: CDManager.shared.viewContext)
gameDict[game.uuid] = cdGame gameDict[game.uuid] = cdGame
cdGame.name = game.name cdGame.name = game.name ?? "n/a"
cdGame.uuid = game.uuid cdGame.uuid = game.uuid
cdGame.inWishlist = game.inWishlist cdGame.inWishlist = game.inWishlist
cdGame.isFinished = game.isFinished cdGame.isFinished = game.isFinished
cdGame.finishedDate = game.finishedDate
cdGame.lentTo = game.lentTo cdGame.lentTo = game.lentTo
cdGame.cover_icloud_path = game.cover_icloud_path cdGame.cover_icloud_path = game.cover_icloud_path
cdGame.pickupDescription = game.pickupDescription cdGame.pickupDescription = game.pickupDescription
cdGame.isDigital = game.isDigital
if let date = Date.from(string: game.createdAt) { if let date = Date.from(string: game.createdAt) {
cdGame.createdAt = date cdGame.createdAt = date
@@ -85,8 +87,6 @@ class LibraryImport {
print("Could not decode date '\(game.createdAt)' for game '\(cdGame.name)'") print("Could not decode date '\(game.createdAt)' for game '\(cdGame.name)'")
} }
//TODO: cdGame.createdAt = game.createdAt.
cdConsole.addToGames(cdGame) cdConsole.addToGames(cdGame)
cdGame.console = cdConsole cdGame.console = cdConsole
print("Imported: \(cdGame.name) for \(cdConsole.name)") print("Imported: \(cdGame.name) for \(cdConsole.name)")
@@ -108,7 +108,7 @@ class LibraryImport {
private func makeCDConsole(from console : BHLConsole) -> Console { private func makeCDConsole(from console : BHLConsole) -> Console {
let cdConsole = Console(context: CDManager.shared.viewContext) let cdConsole = Console(context: CDManager.shared.viewContext)
cdConsole.name = console.name cdConsole.name = console.name ?? "n/a"
cdConsole.uuid = console.uuid cdConsole.uuid = console.uuid
cdConsole.manufacturer = console.manufacturer cdConsole.manufacturer = console.manufacturer
cdConsole.shortName = console.shortName cdConsole.shortName = console.shortName
@@ -190,11 +190,12 @@ struct BHLibrary : Decodable {
struct BHLGame : Decodable { struct BHLGame : Decodable {
let uuid : UUID let uuid : UUID
let name : String let name : String?
let lentTo : String? let lentTo : String?
let isDigital : Bool let isDigital : Bool
let inWishlist : Bool let inWishlist : Bool
let isFinished : Bool let isFinished : Bool
let finishedDate : Date?
let notes : String? let notes : String?
let createdAt : String let createdAt : String
let pickupDescription : String? let pickupDescription : String?
@@ -222,7 +223,7 @@ struct BHLGameSeries : Decodable {
struct BHLConsole : Decodable { struct BHLConsole : Decodable {
let uuid : UUID let uuid : UUID
let name : String let name : String?
let logo_icloud_path : String? let logo_icloud_path : String?
let manufacturer : String? let manufacturer : String?
let releaseDate : Date let releaseDate : Date

View File

@@ -125,13 +125,13 @@ struct GridCell: View {
.scaledToFit() .scaledToFit()
//.shadow(color: .primary, radius: 5) //.shadow(color: .primary, radius: 5)
.padding([.horizontal, .top], 7) .padding([.horizontal, .top], 7)
Text(console.shortName ?? console.name!).lineLimit(1) Text(console.shortName ?? console.name).lineLimit(1)
} }
}.buttonStyle(PlainButtonStyle()) }.buttonStyle(PlainButtonStyle())
}else{ }else{
NavigationLink(destination: ConsoleLibraryView(console: console)) { NavigationLink(destination: ConsoleLibraryView(console: console)) {
Text(console.shortName ?? console.name!) Text(console.shortName ?? console.name)
} }
} }
} }

View File

@@ -16,7 +16,7 @@ struct ConsoleEditView: View {
var body: some View { var body: some View {
Form { Form {
TextField("Name der Konsole", text: $console.name ?? "n/a") TextField("Name der Konsole", text: $console.name)
TextField("Abkürzung", text: $console.shortName ?? "") TextField("Abkürzung", text: $console.shortName ?? "")
TextField("Hersteller", text: $console.manufacturer ?? "") TextField("Hersteller", text: $console.manufacturer ?? "")
DatePicker(selection: $console.releaseDate, in: ...Date(), displayedComponents: .date) { DatePicker(selection: $console.releaseDate, in: ...Date(), displayedComponents: .date) {

View File

@@ -42,18 +42,42 @@ struct GameSeriesPicker: View {
struct GameDetailView : View { struct GameDetailView : View {
@ObservedObject var game : Game @ObservedObject var game : Game
@State private var showDeleteAlert : Bool = false
@State var hasFinishedDate : Bool = false
@State var playthroughDate : Date = Date()
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode> @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State private var showDeleteAlert : Bool = false
@State var isImportingCover : Bool = false @State var isImportingCover : Bool = false
@State var isLent : Bool = false
let defaultImage = UIImage() let defaultImage = UIImage()
@State var hasFinishedDate_raw : Bool = false
private var hasFinishedDate: Binding<Bool> {
Binding<Bool>(
get: { self.hasFinishedDate_raw || self.game.finishedDate != .none },
set: {
hasFinishedDate_raw = $0
if !$0 { self.game.finishedDate = .none }
}
)
}
@State var isLent_raw : Bool = false
private var isLent: Binding<Bool> {
Binding<Bool>(
get: { self.isLent_raw || (self.game.lentTo != .none && self.game.lentTo != "") },
set: {
isLent_raw = $0
if !$0 { self.game.lentTo = .none }
}
)
}
var finishedDateBinding: Binding<Date> {
Binding<Date>(
get: { self.game.finishedDate ?? Date() },
set: { self.game.finishedDate = $0 })
}
var GameIsFinished : some View { var GameIsFinished : some View {
Group { Group {
Toggle(isOn: $game.isFinished , label: { Toggle(isOn: $game.isFinished , label: {
@@ -61,16 +85,16 @@ struct GameDetailView : View {
}) })
if game.isFinished { if game.isFinished {
Toggle(isOn: $hasFinishedDate, label: { Toggle(isOn: hasFinishedDate, label: {
Text("Gibts ein Datum") Text("Gibts ein Datum")
}) })
} }
if hasFinishedDate && game.isFinished { if self.hasFinishedDate.wrappedValue && game.isFinished {
DatePicker("Durchgezockt am", DatePicker("Durchgezockt am",
selection: $playthroughDate, selection: finishedDateBinding,
in: ...Date(), in: ...Date(),
displayedComponents: [.date]) displayedComponents: [.date])
} }
} }
} }
@@ -78,7 +102,7 @@ struct GameDetailView : View {
var body: some View { var body: some View {
Form { Form {
Section { Section {
TextField("Videogame name", text: $game.name ?? "") TextField("Videogame name", text: $game.name)
//Gray color should indicate immutable data //Gray color should indicate immutable data
Text("\(game.console?.name ?? "No console")").foregroundColor(.gray) Text("\(game.console?.name ?? "No console")").foregroundColor(.gray)
@@ -101,15 +125,11 @@ struct GameDetailView : View {
Text("In Wunschliste") Text("In Wunschliste")
}) })
Toggle(isOn: $isLent, label: { Toggle(isOn: isLent, label: {
Text("Verliehen?") Text("Verliehen?")
}).onReceive(game.objectWillChange) { _ in })
self.isLent = self.game.lentTo != "";
}.onAppear() {
self.isLent = self.game.lentTo != "";
}
if isLent { if isLent.wrappedValue {
TextField("Verliehen an", text: $game.lentTo ?? "") TextField("Verliehen an", text: $game.lentTo ?? "")
} }

View File

@@ -24,7 +24,7 @@ struct GamePickupsView: View {
var body: some View { var body: some View {
List(games) { game in List(games) { game in
NavigationLink(destination: GameDetailView(game: game)) { NavigationLink(destination: GameDetailView(game: game)) {
Text("\(game.name!)") Text("\(game.name)")
} }
} }
.padding(.top) // Workaround, damit die Liste beim scrollen nicht unter der NavigationView angezeigt wird .padding(.top) // Workaround, damit die Liste beim scrollen nicht unter der NavigationView angezeigt wird

View File

@@ -30,7 +30,7 @@ struct GameSeriesLibraryView: View {
var body: some View { var body: some View {
List(games) { game in List(games) { game in
NavigationLink(destination: GameDetailView(game: game)) { NavigationLink(destination: GameDetailView(game: game)) {
Text("\(game.name!)") Text("\(game.name)")
if game.isDigital { if game.isDigital {
Image("digitalGame") Image("digitalGame")

View File

@@ -83,12 +83,13 @@ struct Overview: View {
Group { Group {
Image(uiImage: ICloudManager.imageFrom(path: console.logo_icloud_path) ?? defaultImage) Image(uiImage: ICloudManager.imageFrom(path: console.logo_icloud_path) ?? defaultImage)
.resizable() .resizable()
.scaledToFit()
.padding(10) .padding(10)
.cornerRadius(5) .cornerRadius(5)
} }
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
Text("\(console.name!)") Text("\(console.name)")
.font(.caption) .font(.caption)
.frame(width: 100) .frame(width: 100)
@@ -122,7 +123,7 @@ struct Overview: View {
} }
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
Text("\(game.name!)") Text("\(game.name)")
.font(.caption) .font(.caption)
.frame(width: 100) .frame(width: 100)

View File

@@ -24,6 +24,7 @@
<entity name="Game" representedClassName="Game" syncable="YES"> <entity name="Game" representedClassName="Game" syncable="YES">
<attribute name="cover_icloud_path" optional="YES" attributeType="String"/> <attribute name="cover_icloud_path" optional="YES" attributeType="String"/>
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/> <attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="finishedDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="inWishlist" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> <attribute name="inWishlist" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="isDigital" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> <attribute name="isDigital" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="isFinished" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> <attribute name="isFinished" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
@@ -51,7 +52,7 @@
<elements> <elements>
<element name="Accessory" positionX="-265.9140625" positionY="29.15625" width="128" height="149"/> <element name="Accessory" positionX="-265.9140625" positionY="29.15625" width="128" height="149"/>
<element name="Console" positionX="-535.7890625" positionY="56.03515625" width="128" height="164"/> <element name="Console" positionX="-535.7890625" positionY="56.03515625" width="128" height="164"/>
<element name="Game" positionX="-288.828125" positionY="276.7421875" width="128" height="245"/> <element name="Game" positionX="-288.828125" positionY="276.7421875" width="128" height="260"/>
<element name="GameSeries" positionX="-686.828125" positionY="359.20703125" width="128" height="89"/> <element name="GameSeries" positionX="-686.828125" positionY="359.20703125" width="128" height="89"/>
<element name="GameSeriesCover" positionX="-477" positionY="180" width="128" height="44"/> <element name="GameSeriesCover" positionX="-477" positionY="180" width="128" height="44"/>
</elements> </elements>