145 lines
4.9 KiB
Swift
145 lines
4.9 KiB
Swift
//
|
|
// DraftsView.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 11/9/22.
|
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
@available(iOS, obsoleted: 16.0)
|
|
struct DraftsRepresentable: UIViewControllerRepresentable {
|
|
typealias UIViewControllerType = UIHostingController<DraftsView>
|
|
|
|
let currentDraft: Draft
|
|
let mastodonController: MastodonController
|
|
|
|
func makeUIViewController(context: Context) -> UIHostingController<DraftsView> {
|
|
return UIHostingController(rootView: DraftsView(currentDraft: currentDraft, mastodonController: mastodonController))
|
|
}
|
|
|
|
func updateUIViewController(_ uiViewController: UIHostingController<DraftsView>, context: Context) {
|
|
}
|
|
}
|
|
|
|
struct DraftsView: View {
|
|
let currentDraft: Draft
|
|
// don't pass this in via the environment b/c it crashes on macOS (at least, in Designed for iPad mode) since the environment doesn't get propagated through the modal popup window or something
|
|
let mastodonController: MastodonController
|
|
@EnvironmentObject var uiState: ComposeUIState
|
|
@StateObject private var draftsManager = DraftsManager.shared
|
|
@State private var draftForDifferentReply: Draft?
|
|
|
|
private var visibleDrafts: [Draft] {
|
|
draftsManager.sorted.filter {
|
|
$0.accountID == mastodonController.accountInfo!.id && $0.id != currentDraft.id
|
|
}
|
|
}
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
List {
|
|
ForEach(visibleDrafts) { draft in
|
|
Button {
|
|
maybeSelectDraft(draft)
|
|
} label: {
|
|
DraftView(draft: draft)
|
|
}
|
|
.contextMenu {
|
|
Button(role: .destructive) {
|
|
draftsManager.remove(draft)
|
|
} label: {
|
|
Label("Delete Draft", systemImage: "trash")
|
|
}
|
|
}
|
|
.onDrag {
|
|
let activity = UserActivityManager.editDraftActivity(id: draft.id, accountID: mastodonController.accountInfo!.id)
|
|
activity.displaysAuxiliaryScene = true
|
|
return NSItemProvider(object: activity)
|
|
}
|
|
}
|
|
.onDelete { indices in
|
|
indices
|
|
.map { visibleDrafts[$0] }
|
|
.forEach { draftsManager.remove($0) }
|
|
}
|
|
.appGroupedListRowBackground()
|
|
}
|
|
.listStyle(.plain)
|
|
.appGroupedListBackground(container: DraftsRepresentable.UIViewControllerType.self)
|
|
.navigationTitle(Text("Drafts"))
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .cancellationAction) {
|
|
Button("Cancel") {
|
|
uiState.isShowingDraftsList = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.alertWithData("Different Reply", data: $draftForDifferentReply) { draft in
|
|
Button("Cancel", role: .cancel) {
|
|
draftForDifferentReply = nil
|
|
}
|
|
Button("Restore Draft") {
|
|
uiState.delegate?.selectDraft(draft)
|
|
}
|
|
} message: { draft in
|
|
Text("The selected draft is a reply to a different post, do you wish to use it?")
|
|
}
|
|
}
|
|
|
|
private func maybeSelectDraft(_ draft: Draft) {
|
|
if draft.inReplyToID != currentDraft.inReplyToID,
|
|
currentDraft.hasContent {
|
|
draftForDifferentReply = draft
|
|
} else {
|
|
uiState.delegate?.selectDraft(draft)
|
|
}
|
|
}
|
|
}
|
|
|
|
struct DraftView: View {
|
|
@ObservedObject private var draft: Draft
|
|
|
|
init(draft: Draft) {
|
|
self._draft = ObservedObject(wrappedValue: draft)
|
|
}
|
|
|
|
var body: some View {
|
|
HStack {
|
|
VStack(alignment: .leading) {
|
|
if draft.contentWarningEnabled {
|
|
Text(draft.contentWarning)
|
|
.font(.body.bold())
|
|
.foregroundColor(.secondary)
|
|
}
|
|
|
|
Text(draft.text)
|
|
.font(.body)
|
|
|
|
HStack(spacing: 8) {
|
|
ForEach(draft.attachments) { attachment in
|
|
ComposeAttachmentImage(attachment: attachment, fullSize: false)
|
|
.frame(width: 50, height: 50)
|
|
.cornerRadius(5)
|
|
}
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
|
|
Text(draft.lastModified.timeAgoString())
|
|
.font(.body)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
}
|
|
}
|
|
|
|
//struct DraftsView_Previews: PreviewProvider {
|
|
// static var previews: some View {
|
|
// DraftsView(currentDraft: Draft(accountID: ""))
|
|
// }
|
|
//}
|