Editor: Add image ALT

This commit is contained in:
Thomas Ricouard 2023-01-03 19:30:27 +01:00
parent 64c57a241a
commit 7ce3446030
5 changed files with 135 additions and 13 deletions

View file

@ -2,18 +2,26 @@ import Foundation
public enum Media: Endpoint {
case medias
case media(id: String)
case media(id: String, description: String?)
public func path() -> String {
switch self {
case .medias:
return "media"
case let .media(id):
case let .media(id, _):
return "media/\(id)"
}
}
public func queryItems() -> [URLQueryItem]? {
return nil
switch self {
case let .media(_, description):
if let description {
return [.init(name: "description", value: description)]
}
return nil
default:
return nil
}
}
}

View file

@ -0,0 +1,69 @@
import SwiftUI
import Models
import DesignSystem
import Shimmer
struct StatusEditorMediaEditView: View {
@Environment(\.dismiss) private var dismiss
@EnvironmentObject private var theme: Theme
@ObservedObject var viewModel: StatusEditorViewModel
let container: StatusEditorViewModel.ImageContainer
@State private var imageDescription: String = ""
var body: some View {
NavigationStack {
Form {
Section {
TextField("Image description", text: $imageDescription, axis: .horizontal)
}
.listRowBackground(theme.primaryBackgroundColor)
Section {
if let url = container.mediaAttachement?.url {
AsyncImage(
url: url,
content: { image in
image
.resizable()
.aspectRatio(contentMode: .fill)
.cornerRadius(8)
.padding(8)
},
placeholder: {
RoundedRectangle(cornerRadius: 8)
.fill(Color.gray)
.frame(height: 200)
.shimmering()
})
}
}
.listRowBackground(theme.primaryBackgroundColor)
}
.scrollContentBackground(.hidden)
.background(theme.secondaryBackgroundColor)
.onAppear {
imageDescription = container.mediaAttachement?.description ?? ""
}
.navigationTitle("Edit Image")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Done") {
if !imageDescription.isEmpty {
Task {
await viewModel.addDescription(container: container, description: imageDescription)
}
}
dismiss()
}
}
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
dismiss()
}
}
}
}
}
}

View file

@ -6,6 +6,7 @@ import NukeUI
struct StatusEditorMediaView: View {
@ObservedObject var viewModel: StatusEditorViewModel
@State private var editingContainer: StatusEditorViewModel.ImageContainer?
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
@ -14,22 +15,24 @@ struct StatusEditorMediaView: View {
if container.image != nil {
makeLocalImage(container: container)
} else if let url = container.mediaAttachement?.url {
ZStack(alignment: .topTrailing) {
makeLazyImage(url: url)
Button {
withAnimation {
viewModel.mediasImages.removeAll(where: { $0.id == container.id })
Menu {
makeImageMenu(container: container)
} label: {
ZStack(alignment: .bottomTrailing) {
makeLazyImage(url: url)
if container.mediaAttachement?.description?.isEmpty == false {
altMarker
}
} label: {
Image(systemName: "xmark.circle")
}
.padding(8)
}
}
}
}
.padding(.horizontal, .layoutPadding)
}
.sheet(item: $editingContainer) { container in
StatusEditorMediaEditView(viewModel: viewModel, container: container)
}
}
private func makeLocalImage(container: StatusEditorViewModel.ImageContainer) -> some View {
@ -84,5 +87,33 @@ struct StatusEditorMediaView: View {
.frame(width: 150, height: 150)
.cornerRadius(8)
}
@ViewBuilder
private func makeImageMenu(container: StatusEditorViewModel.ImageContainer) -> some View {
Button {
editingContainer = container
} label: {
Label(editingContainer?.mediaAttachement?.description?.isEmpty == false ?
"Edit description" : "Add description",
systemImage: "pencil.line")
}
Button(role: .destructive) {
withAnimation {
viewModel.mediasImages.removeAll(where: { $0.id == container.id })
}
} label: {
Label("Delete", systemImage: "trash")
}
}
private var altMarker: some View {
Button {
} label: {
Text("ALT")
.font(.caption2)
}
.padding(4)
.background(.thinMaterial)
.cornerRadius(8)
}
}

View file

@ -304,6 +304,20 @@ public class StatusEditorViewModel: ObservableObject {
}
}
}
func addDescription(container: ImageContainer, description: String) async {
guard let client, let attachment = container.mediaAttachement else { return }
if let index = indexOf(container: container) {
let originalContainer = mediasImages[index]
do {
let media: MediaAttachement = try await client.put(endpoint: Media.media(id: attachment.id,
description: description))
mediasImages[index] = .init(image: nil, mediaAttachement: media, error: nil)
} catch {
}
}
}
private func uploadMedia(data: Data) async throws -> MediaAttachement? {
guard let client else { return nil }

View file

@ -20,7 +20,7 @@ For contributors and myself, here is a todo list of features that could be added
- [ ] DM / Conversations
- [X] Lists support
- [X] Display images alt
- [ ] Editor: Post image alts
- [X] Editor: Post image alts
- [ ] Editor: Add / Edit polls
- [ ] Editor: Support video types
- [ ] Editor: Add photos from camera