Select First Tag Suggestion using TAB

This commit is contained in:
Otavio Cordeiro 2025-12-28 01:02:45 +01:00 committed by Otávio
parent 4d95a7d40f
commit eaef589399
6 changed files with 72 additions and 3 deletions

View file

@ -74,7 +74,7 @@ struct EditPictureView: View {
.autocorrectionDisabled(true) .autocorrectionDisabled(true)
.font(.body.monospaced()) .font(.body.monospaced())
.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, or press tab to select the first suggestion")
.onSubmit { .onSubmit {
withAnimation { withAnimation {
viewModel.addTag(viewModel.tagInput) viewModel.addTag(viewModel.tagInput)
@ -83,6 +83,14 @@ struct EditPictureView: View {
.onChange(of: viewModel.tagInput) { .onChange(of: viewModel.tagInput) {
viewModel.updateTagSuggestions(from: existingTags.map(\.title)) viewModel.updateTagSuggestions(from: existingTags.map(\.title))
} }
.onKeyPress(.tab) {
do {
try viewModel.selectFistTagSuggestion()
return .handled
} catch {
return .ignored
}
}
} }
@ViewBuilder @ViewBuilder

View file

@ -7,6 +7,13 @@ import PicsRepository
@Observable @Observable
final class EditPictureViewModel { final class EditPictureViewModel {
// MARK: - Nested types
enum TagSelectionError: Error {
case noSuggestions
}
// MARK: - Properties // MARK: - Properties
let pictureID: String let pictureID: String
@ -108,4 +115,12 @@ final class EditPictureViewModel {
func removeTag(_ tag: String) { func removeTag(_ tag: String) {
tags.removeAll { $0 == tag } tags.removeAll { $0 == tag }
} }
func selectFistTagSuggestion() throws(TagSelectionError) {
guard let tag = suggestedTags.first else {
throw .noSuggestions
}
addTag(tag)
}
} }

View file

@ -185,7 +185,7 @@ struct UploadView: View {
.autocorrectionDisabled(true) .autocorrectionDisabled(true)
.font(.body.monospaced()) .font(.body.monospaced())
.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, or press tab to select the first suggestion")
.onSubmit { .onSubmit {
withAnimation(.easeInOut(duration: 0.2)) { withAnimation(.easeInOut(duration: 0.2)) {
viewModel.addTag(viewModel.tagInput) viewModel.addTag(viewModel.tagInput)
@ -194,6 +194,14 @@ struct UploadView: View {
.onChange(of: viewModel.tagInput) { .onChange(of: viewModel.tagInput) {
viewModel.updateTagSuggestions(from: existingTags.map(\.title)) viewModel.updateTagSuggestions(from: existingTags.map(\.title))
} }
.onKeyPress(.tab) {
do {
try viewModel.selectFistTagSuggestion()
return .handled
} catch {
return .ignored
}
}
} }
@ViewBuilder @ViewBuilder

View file

@ -9,6 +9,13 @@ import UniformTypeIdentifiers
@Observable @Observable
final class UploadViewModel { final class UploadViewModel {
// MARK: - Nested types
enum TagSelectionError: Error {
case noSuggestions
}
// MARK: - Properties // MARK: - Properties
var caption = "" var caption = ""
@ -145,6 +152,14 @@ final class UploadViewModel {
tags.removeAll { $0 == tag } tags.removeAll { $0 == tag }
} }
func selectFistTagSuggestion() throws(TagSelectionError) {
guard let tag = suggestedTags.first else {
throw .noSuggestions
}
addTag(tag)
}
// MARK: - Private // MARK: - Private
private func setUpObservers() { private func setUpObservers() {

View file

@ -122,7 +122,7 @@ struct EditorView: View {
.autocorrectionDisabled(true) .autocorrectionDisabled(true)
.font(.body.monospaced()) .font(.body.monospaced())
.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, or press tab to select the first suggestion")
.onSubmit { .onSubmit {
withAnimation { withAnimation {
viewModel.addTag(viewModel.tagInput) viewModel.addTag(viewModel.tagInput)
@ -131,6 +131,14 @@ struct EditorView: View {
.onChange(of: viewModel.tagInput) { .onChange(of: viewModel.tagInput) {
viewModel.updateTagSuggestions(from: existingTags.map(\.title)) viewModel.updateTagSuggestions(from: existingTags.map(\.title))
} }
.onKeyPress(.tab) {
do {
try viewModel.selectFistTagSuggestion()
return .handled
} catch {
return .ignored
}
}
} }
@ViewBuilder @ViewBuilder

View file

@ -7,6 +7,13 @@ import WeblogRepository
@Observable @Observable
final class EditorViewModel { final class EditorViewModel {
// MARK: - Nested types
enum TagSelectionError: Error {
case noSuggestions
}
// MARK: - Properties // MARK: - Properties
var body: String var body: String
@ -115,4 +122,12 @@ final class EditorViewModel {
func removeTag(_ tag: String) { func removeTag(_ tag: String) {
tags.removeAll { $0 == tag } tags.removeAll { $0 == tag }
} }
func selectFistTagSuggestion() throws(TagSelectionError) {
guard let tag = suggestedTags.first else {
throw .noSuggestions
}
addTag(tag)
}
} }