mirror of
https://github.com/otaviocc/Triton.git
synced 2026-01-30 04:04:27 +00:00
Add new revamped drag-and-drop area
This commit is contained in:
parent
07ea603267
commit
833f9e920d
2 changed files with 63 additions and 29 deletions
|
|
@ -36,9 +36,6 @@ struct UploadView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.onDrop(of: [.image], isTargeted: $viewModel.isDragging) { providers -> Bool in
|
|
||||||
handleDrop(providers: providers)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
@ -50,20 +47,8 @@ struct UploadView: View {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private func makeSidebarView() -> some View {
|
|
||||||
VStack {
|
|
||||||
makePictureView()
|
|
||||||
makePicturePickerView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private func makeContentView() -> some View {
|
private func makeContentView() -> some View {
|
||||||
ZStack {
|
|
||||||
if viewModel.isDragging {
|
|
||||||
makeDropZoneView()
|
|
||||||
} else {
|
|
||||||
VStack {
|
VStack {
|
||||||
HStack(alignment: .top) {
|
HStack(alignment: .top) {
|
||||||
makeSidebarView()
|
makeSidebarView()
|
||||||
|
|
@ -73,21 +58,54 @@ struct UploadView: View {
|
||||||
makeVisibilityView()
|
makeVisibilityView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func makeSidebarView() -> some View {
|
||||||
|
VStack {
|
||||||
|
if viewModel.imageData != nil {
|
||||||
|
makePictureView()
|
||||||
|
makeRemoveButtonView()
|
||||||
|
} else {
|
||||||
|
ZStack {
|
||||||
|
makeDropZoneBorder()
|
||||||
|
makeDropZoneContentView()
|
||||||
|
}
|
||||||
|
.onDrop(of: [.image], isTargeted: $viewModel.isDragging) { providers -> Bool in
|
||||||
|
handleDrop(providers: providers)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private func makeDropZoneView() -> some View {
|
private func makeDropZoneBorder() -> some View {
|
||||||
RoundedRectangle(cornerRadius: 8)
|
RoundedRectangle(cornerRadius: 8)
|
||||||
.fill(
|
.fill(
|
||||||
AnyShapeStyle(
|
AnyShapeStyle(
|
||||||
viewModel.isDragging ? Color.accentColor.opacity(0.1) : .clear
|
viewModel.isDragging ? Color.accentColor.opacity(0.3) : .secondary.opacity(0.05)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.strokeBorder(
|
.stroke(Color.accentColor, lineWidth: 1.0)
|
||||||
viewModel.isDragging ? Color.accentColor : .secondary.opacity(0.3),
|
.opacity(0.3)
|
||||||
style: StrokeStyle(lineWidth: 2, dash: [8, 4])
|
.frame(minHeight: 200)
|
||||||
)
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func makeDropZoneContentView() -> some View {
|
||||||
|
VStack(spacing: 12) {
|
||||||
|
Image(systemName: viewModel.dropZoneImageName)
|
||||||
|
.font(.system(size: 48))
|
||||||
|
.foregroundStyle(viewModel.isDragging ? Color.accentColor : .secondary)
|
||||||
|
|
||||||
|
if !viewModel.isDragging {
|
||||||
|
Text("Drag your picture here or click the button to select one from your Photo Library")
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
makePicturePickerView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.vertical, 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
|
@ -108,7 +126,7 @@ struct UploadView: View {
|
||||||
matching: .images,
|
matching: .images,
|
||||||
photoLibrary: .shared()
|
photoLibrary: .shared()
|
||||||
) {
|
) {
|
||||||
Text("Select Picture")
|
Text("Select from Library")
|
||||||
}
|
}
|
||||||
.help("Choose an image from your photo library")
|
.help("Choose an image from your photo library")
|
||||||
.onChange(of: selectedItem) {
|
.onChange(of: selectedItem) {
|
||||||
|
|
@ -119,6 +137,20 @@ struct UploadView: View {
|
||||||
.buttonStyle(.borderedProminent)
|
.buttonStyle(.borderedProminent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func makeRemoveButtonView() -> some View {
|
||||||
|
Button {
|
||||||
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
|
viewModel.imageData = nil
|
||||||
|
selectedItem = nil
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Label("Remove", systemImage: "trash")
|
||||||
|
}
|
||||||
|
.help("Remove selected image")
|
||||||
|
.buttonStyle(.bordered)
|
||||||
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private func makeEditorView() -> some View {
|
private func makeEditorView() -> some View {
|
||||||
VStack {
|
VStack {
|
||||||
|
|
@ -155,7 +187,7 @@ struct UploadView: View {
|
||||||
.textFieldCard()
|
.textFieldCard()
|
||||||
.help("Enter a tag and press the return key to add it")
|
.help("Enter a tag and press the return key to add it")
|
||||||
.onSubmit {
|
.onSubmit {
|
||||||
withAnimation {
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
viewModel.addTag(viewModel.tagInput)
|
viewModel.addTag(viewModel.tagInput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +203,7 @@ struct UploadView: View {
|
||||||
tags: viewModel.suggestedTags,
|
tags: viewModel.suggestedTags,
|
||||||
helpText: { "Add existing tag '\($0)'" }
|
helpText: { "Add existing tag '\($0)'" }
|
||||||
) { tag in
|
) { tag in
|
||||||
withAnimation {
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
viewModel.addTag(tag)
|
viewModel.addTag(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -186,7 +218,7 @@ struct UploadView: View {
|
||||||
style: .remove,
|
style: .remove,
|
||||||
helpText: { "Remove tag '\($0)'" }
|
helpText: { "Remove tag '\($0)'" }
|
||||||
) { tag in
|
) { tag in
|
||||||
withAnimation {
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
viewModel.removeTag(tag)
|
viewModel.removeTag(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,6 @@ final class UploadViewModel {
|
||||||
|
|
||||||
@ObservationIgnored private var observationTask: Task<Void, Never>?
|
@ObservationIgnored private var observationTask: Task<Void, Never>?
|
||||||
|
|
||||||
// MARK: - Computed Properties
|
|
||||||
|
|
||||||
var isSubmitDisabled: Bool {
|
var isSubmitDisabled: Bool {
|
||||||
let trimmedCaption = caption.trimmingCharacters(in: .whitespacesAndNewlines)
|
let trimmedCaption = caption.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
return trimmedCaption.isEmpty || isSubmitting || imageData == nil
|
return trimmedCaption.isEmpty || isSubmitting || imageData == nil
|
||||||
|
|
@ -44,6 +42,10 @@ final class UploadViewModel {
|
||||||
isSubmitting
|
isSubmitting
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dropZoneImageName: String {
|
||||||
|
isDragging ? "photo.badge.plus.fill" : "photo.badge.plus"
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Lifecycle
|
// MARK: - Lifecycle
|
||||||
|
|
||||||
init(
|
init(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue