Add images to posts, saving

This commit is contained in:
Christoph Hagen
2024-11-20 23:46:54 +01:00
parent cb22ae34f2
commit a35c2d669e
21 changed files with 415 additions and 149 deletions

View File

@ -0,0 +1,60 @@
import SwiftUI
struct ImagePickerView: View {
@Binding
var showImagePicker: Bool
@ObservedObject
var post: LocalizedPost
@EnvironmentObject
private var content: Content
@Environment(\.language)
private var language
init(showImagePicker: Binding<Bool>, post: LocalizedPost) {
self._showImagePicker = showImagePicker
self.post = post
}
@State
private var selectedImage: ImageResource?
var body: some View {
VStack {
Text("Select the image to add")
List(content.images, selection: $selectedImage) { image in
Text("\(image.id)")
.tag(image)
}
.frame(minHeight: 300)
HStack {
Button("Add") {
DispatchQueue.main.async {
if let selectedImage {
print("Added image")
post.images.append(selectedImage)
} else {
print("No image to add")
}
}
showImagePicker = false
}
.disabled(selectedImage == nil)
Button("Cancel", role: .cancel) {
showImagePicker = false
}
}
}
.navigationTitle("Pick a page")
.padding()
}
}
#Preview {
ImagePickerView(showImagePicker: .constant(true),
post: LocalizedPost.english)
.environmentObject(Content.mock)
}

View File

@ -22,16 +22,45 @@ private struct NavigationIcon: View {
struct PostImageGalleryView: View {
let images: [Image]
@ObservedObject
var post: LocalizedPost
@State private var currentIndex = 0
@State
private var showImagePicker = false
var body: some View {
ZStack {
images[currentIndex]
.resizable()
.scaledToFit()
if images.count > 1 {
ZStack(alignment: .center) {
ZStack(alignment: .bottomTrailing) {
ZStack(alignment: .bottom) {
post.images[currentIndex]
.imageToDisplay
.resizable()
.scaledToFit()
if post.images.count > 1 {
HStack(spacing: 8) {
ForEach(0..<post.images.count, id: \.self) { index in
Circle()
.fill(index == currentIndex ? Color.white : Color.gray)
.frame(width: 10, height: 10)
}
}
.padding(.bottom, 10)
}
}
Button(action: { showImagePicker = true }) {
Image(systemSymbol: .plusCircleFill)
.resizable()
.renderingMode(.template)
.foregroundStyle(.blue.opacity(0.7))
.frame(width: 30, height: 30)
.padding()
}
}
.buttonStyle(.plain)
.foregroundStyle(.blue)
if post.images.count > 1 {
HStack {
Button(action: previous) {
NavigationIcon(symbol: .chevronLeft, edge: .trailing)
@ -46,38 +75,33 @@ struct PostImageGalleryView: View {
.buttonStyle(.plain)
.padding()
}
VStack {
Spacer()
HStack(spacing: 8) {
ForEach(0..<images.count, id: \.self) { index in
Circle()
.fill(index == currentIndex ? Color.white : Color.gray) // Change color based on current index
.frame(width: 10, height: 10)
}
}
.padding(.bottom, 10)
}
}
}
.sheet(isPresented: $showImagePicker) {
ImagePickerView(
showImagePicker: $showImagePicker,
post: post
)
}
}
private func previous() {
if currentIndex > 0 {
currentIndex -= 1
} else {
currentIndex = images.count - 1
currentIndex = post.images.count - 1
}
}
private func next() {
if currentIndex < images.count - 1 {
if currentIndex < post.images.count - 1 {
currentIndex += 1
} else {
currentIndex = 0 // Wrap to first image
currentIndex = 0
}
}
}
#Preview(traits: .fixedLayout(width: 300, height: 300)) {
PostImageGalleryView(images: MockImage.images.map { $0.imageToDisplay })
#Preview(traits: .fixedLayout(width: 300, height: 250)) {
PostImageGalleryView(post: .german)
}

View File

@ -14,6 +14,12 @@ struct PostView: View {
@State
private var showPagePicker = false
@State
private var showImagePicker = false
@State
private var showTagPicker = false
private var linkedPageText: String {
if let page = post.linkedPage {
return page.localized(in: language).title
@ -23,8 +29,15 @@ struct PostView: View {
var body: some View {
VStack(alignment: .center) {
if !post.localized(in: language).images.isEmpty {
PostImageGalleryView(images: post.localized(in: language).displayImages)
if post.localized(in: language).images.isEmpty {
Button(action: { showImagePicker = true }) {
Text("Add image")
}
.buttonStyle(.plain)
.foregroundStyle(.blue)
.padding(.top)
} else {
PostImageGalleryView(post: post.localized(in: language))
.aspectRatio(1.33, contentMode: .fill)
}
VStack(alignment: .leading) {
@ -35,10 +48,10 @@ struct PostView: View {
Spacer()
Toggle("Draft", isOn: $post.isDraft)
}
.foregroundStyle(ColorPalette.postDate)
.foregroundStyle(.secondary)
TextField("", text: post.localized(in: language).editableTitle())
.font(.system(size: 24, weight: .bold))
.foregroundStyle(Color.white)
.foregroundStyle(Color.primary)
.textFieldStyle(.plain)
.lineLimit(2)
FlowHStack {
@ -51,20 +64,20 @@ struct PostView: View {
remove(tag: tag)
}
}
Button(action: showTagList) {
Button(action: { showTagPicker = true }) {
SwiftUI.Image(systemSymbol: .plusCircleFill)
.resizable()
.aspectRatio(1, contentMode: .fit)
.frame(height: 18)
.foregroundColor(ColorPalette.tagForeground)
.opacity(0.7)
.foregroundColor(Color.blue)
//.opacity(0.7)
.padding(.top, 3)
}
.buttonStyle(.plain)
}
TextEditor(text: post.localized(in: language).editableContent())
.font(.body)
.foregroundStyle(ColorPalette.postText)
.foregroundStyle(.secondary)
.textEditorStyle(.plain)
.padding(.leading, -5)
.scrollDisabled(true)
@ -73,12 +86,12 @@ struct PostView: View {
Text(linkedPageText)
}
.buttonStyle(.plain)
.foregroundStyle(ColorPalette.postDate)
.foregroundStyle(ColorPalette.link)
}
}
.padding()
}
.background(ColorPalette.postBackground)
.background(Color.secondary.colorInvert())
.cornerRadius(8)
.sheet(isPresented: $showDatePicker) {
DatePickerView(
@ -90,26 +103,28 @@ struct PostView: View {
showPagePicker: $showPagePicker,
selectedPage: $post.linkedPage)
}
.sheet(isPresented: $showImagePicker) {
ImagePickerView(
showImagePicker: $showImagePicker,
post: post.localized(in: language)
)
}
}
private func remove(tag: Tag) {
post.tags = post.tags.filter {$0.id != tag.id }
}
private func showTagList() {
}
}
#Preview(traits: .fixedLayout(width: 450, height: 600)) {
List {
PostView(post: .fullMock)
.listRowSeparator(.hidden)
.listRowBackground(ColorPalette.listBackground)
//.listRowBackground(ColorPalette.listBackground)
.environment(\.language, ContentLanguage.german)
PostView(post: .mock)
.listRowSeparator(.hidden)
.listRowBackground(ColorPalette.listBackground)
//.listRowBackground(ColorPalette.listBackground)
}
.listStyle(.plain)
//.listStyle(.plain)
}

View File

@ -9,18 +9,12 @@ struct TagView: View {
let tag: LocalizedText
let icon: SFSymbol
let iconSize: CGFloat
init(tag: LocalizedText, icon: SFSymbol = .xCircleFill, iconSize: CGFloat = 12.0) {
init(tag: LocalizedText) {
self.tag = tag
self.icon = icon
self.iconSize = iconSize
}
static var add: TagView {
.init(tag: LocalizedText(en: "Add", de: "Mehr"), icon: .plusCircleFill)
.init(tag: LocalizedText(en: "Add", de: "Mehr"))
}
var body: some View {
@ -28,16 +22,11 @@ struct TagView: View {
Text(tag.getText(for: language))
.font(.subheadline)
.padding(.leading, 2)
SwiftUI.Image(systemSymbol: icon)
.font(.system(size: iconSize, weight: .black, design: .rounded))
.opacity(0.7)
.padding(.leading, -5)
}
.foregroundColor(ColorPalette.tagForeground)
.font(.caption2)
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(ColorPalette.tagBackground)
.background(Color.accentColor)
.cornerRadius(8)
}
}
@ -49,5 +38,5 @@ struct TagView: View {
TagView(tag: LocalizedText(en: "Some", de: "Etwas"))
.environment(\.language, ContentLanguage.english)
TagView.add
}
}.background(Color.secondary)
}