mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-22 16:31:00 +00:00
Editor: Add image ALT
This commit is contained in:
parent
64c57a241a
commit
7ce3446030
5 changed files with 135 additions and 13 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
@ -85,4 +88,32 @@ struct StatusEditorMediaView: View {
|
|||
.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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -305,6 +305,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 }
|
||||
return try await client.mediaUpload(mimeType: "image/jpeg", data: data)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue