add illustration image for worlds
This commit is contained in:
1 parent
85259446b1
commit
21614116fc
7 files changed
+120
-15
No files matched your search
+8
@@ -10,5 +10,13 @@
|
|||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
<dict>
|
||||||
|
<key>2C96045430463C2E0003A2A8</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -36,12 +36,19 @@ struct WorldCardView : View {
|
|||||||
.padding(.horizontal, 4)
|
.padding(.horizontal, 4)
|
||||||
|
|
||||||
}
|
}
|
||||||
.frame(height: 220)
|
.frame(height: 250)
|
||||||
.background {
|
.background {
|
||||||
|
if let dataImage = world.illustrationData,
|
||||||
|
let uiImage = UIImage(data: dataImage) {
|
||||||
|
Image(uiImage: uiImage)
|
||||||
|
.resizable()
|
||||||
|
.scaledToFill()
|
||||||
|
}else {
|
||||||
Image(systemName: "globe.europe.africa")
|
Image(systemName: "globe.europe.africa")
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFill()
|
.scaledToFill()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 20))
|
.clipShape(RoundedRectangle(cornerRadius: 20))
|
||||||
.contentShape(RoundedRectangle(cornerRadius: 20))
|
.contentShape(RoundedRectangle(cornerRadius: 20))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,18 +15,20 @@ class World {
|
|||||||
var updatedAt : Date
|
var updatedAt : Date
|
||||||
var name : String
|
var name : String
|
||||||
var overview : String
|
var overview : String
|
||||||
|
@Attribute(.externalStorage) var illustrationData : Data?
|
||||||
|
|
||||||
init(name: String, overview: String) {
|
init(name: String, overview: String, illustrationData: Data?) {
|
||||||
self.id = UUID()
|
self.id = UUID()
|
||||||
self.name = name
|
self.name = name
|
||||||
self.overview = overview
|
self.overview = overview
|
||||||
self.createdAt = Date()
|
self.createdAt = Date()
|
||||||
self.updatedAt = Date()
|
self.updatedAt = Date()
|
||||||
|
self.illustrationData = illustrationData
|
||||||
}
|
}
|
||||||
|
|
||||||
func duplicate() -> World {
|
func duplicate() -> World {
|
||||||
let newWorld = World(
|
let newWorld = World(
|
||||||
name: self.name, overview: self.overview
|
name: self.name, overview: self.overview, illustrationData: self.illustrationData
|
||||||
)
|
)
|
||||||
|
|
||||||
return newWorld
|
return newWorld
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// IllustrationSection.swift
|
||||||
|
// WorldBuilder
|
||||||
|
//
|
||||||
|
// Created by Giovanni Josserand on 05/09/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import PhotosUI
|
||||||
|
|
||||||
|
struct IllustrationSection : View {
|
||||||
|
@Binding var selectedItem: PhotosPickerItem?
|
||||||
|
@Binding var selectedImageData: Data?
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Section("Illustration") {
|
||||||
|
if let selectedImageData, let uiImage = UIImage(data: selectedImageData) {
|
||||||
|
Image(uiImage: uiImage)
|
||||||
|
.resizable()
|
||||||
|
.scaledToFill()
|
||||||
|
.frame(height: 150)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||||
|
.listRowInsets(EdgeInsets())
|
||||||
|
}
|
||||||
|
|
||||||
|
PhotosPicker(
|
||||||
|
selection: $selectedItem,
|
||||||
|
matching: .any(of: [.images, .not(.screenshots)])
|
||||||
|
) {
|
||||||
|
Label(
|
||||||
|
selectedImageData == nil ? "Sélectionner une photo" : "Modifier la photo",
|
||||||
|
systemImage: "photo"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// InformationsSection.swift
|
||||||
|
// WorldBuilder
|
||||||
|
//
|
||||||
|
// Created by Giovanni Josserand on 05/09/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct InformationsSection : View {
|
||||||
|
@Binding var worldName : String
|
||||||
|
@Binding var worldOverview : String
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Section("Informations") {
|
||||||
|
TextField("Nom du monde", text: $worldName)
|
||||||
|
|
||||||
|
TextField(
|
||||||
|
"Description",
|
||||||
|
text: $worldOverview,
|
||||||
|
axis: .vertical
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,14 @@
|
|||||||
// Created by Giovanni Josserand on 01/09/2026.
|
// Created by Giovanni Josserand on 01/09/2026.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// CreateWorldView.swift
|
||||||
|
// WorldBuilder
|
||||||
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import SwiftData
|
import SwiftData
|
||||||
|
import PhotosUI
|
||||||
|
|
||||||
struct CreateWorldView: View {
|
struct CreateWorldView: View {
|
||||||
@State private var worldName = ""
|
@State private var worldName = ""
|
||||||
@@ -19,28 +25,38 @@ struct CreateWorldView: View {
|
|||||||
@State private var showSaveError = false
|
@State private var showSaveError = false
|
||||||
@State private var saveErrorMessage = ""
|
@State private var saveErrorMessage = ""
|
||||||
|
|
||||||
|
@State private var selectedItem: PhotosPickerItem?
|
||||||
|
@State private var selectedImageData: Data?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
Section("Informations") {
|
InformationsSection(
|
||||||
TextField("Nom du monde", text: $worldName)
|
worldName: $worldName,
|
||||||
|
worldOverview: $worldOverview
|
||||||
|
)
|
||||||
|
|
||||||
TextField(
|
IllustrationSection(
|
||||||
"Description",
|
selectedItem: $selectedItem,
|
||||||
text: $worldOverview,
|
selectedImageData: $selectedImageData
|
||||||
axis: .vertical
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
Button("Créer le monde") {
|
Button("Créer le monde") {
|
||||||
let world = World(name: worldName, overview: worldOverview)
|
let world = World(
|
||||||
|
name: worldName,
|
||||||
|
overview: worldOverview,
|
||||||
|
illustrationData: selectedImageData
|
||||||
|
)
|
||||||
|
|
||||||
context.insert(world)
|
context.insert(world)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try context.save()
|
try context.save()
|
||||||
router.selectedTab = .worldsList
|
router.selectedTab = .worldsList
|
||||||
dismiss()
|
dismiss()
|
||||||
} catch {
|
} catch {
|
||||||
saveErrorMessage = "Impossible de sauvegarder le monde : \(error.localizedDescription)"
|
saveErrorMessage =
|
||||||
|
"Impossible de sauvegarder le monde : \(error.localizedDescription)"
|
||||||
showSaveError = true
|
showSaveError = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,5 +77,12 @@ struct CreateWorldView: View {
|
|||||||
} message: {
|
} message: {
|
||||||
Text(saveErrorMessage)
|
Text(saveErrorMessage)
|
||||||
}
|
}
|
||||||
|
.onChange(of: selectedItem) { _, newItem in
|
||||||
|
Task {
|
||||||
|
if let data = try? await newItem?.loadTransferable(type: Data.self) {
|
||||||
|
selectedImageData = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,13 +19,12 @@ struct WorldListView: View {
|
|||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
|
||||||
VStack(alignment: .leading, spacing: 24){
|
VStack(alignment: .leading, spacing: 24){
|
||||||
WorldListHeaderView(worlds: worlds)
|
|
||||||
|
|
||||||
if worlds.isEmpty {
|
if worlds.isEmpty {
|
||||||
EmptyWorldView()
|
EmptyWorldView()
|
||||||
}else{
|
}else{
|
||||||
|
ScrollView {
|
||||||
LazyVGrid(columns: columns){
|
LazyVGrid(columns: columns){
|
||||||
ForEach(worlds) {world in
|
ForEach(worlds) {world in
|
||||||
if isSelecting {
|
if isSelecting {
|
||||||
@@ -64,7 +63,11 @@ struct WorldListView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Bibliothèque")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.padding(.horizontal, 8)
|
.padding(.horizontal, 8)
|
||||||
.frame(maxHeight: .infinity, alignment: .topLeading)
|
.frame(maxHeight: .infinity, alignment: .topLeading)
|
||||||
.modifier(
|
.modifier(
|
||||||
@@ -74,7 +77,6 @@ struct WorldListView: View {
|
|||||||
worlds: worlds
|
worlds: worlds
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
|
||||||
.modifier(
|
.modifier(
|
||||||
WorldListToolbarModifier(
|
WorldListToolbarModifier(
|
||||||
isSelecting: $isSelecting,
|
isSelecting: $isSelecting,
|
||||||
@@ -82,5 +84,6 @@ struct WorldListView: View {
|
|||||||
worldsIsEmpty: worlds.isEmpty
|
worldsIsEmpty: worlds.isEmpty
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user