diff --git a/WorterBuch/SelectableTextView.swift b/WorterBuch/SelectableTextView.swift new file mode 100644 index 0000000..0206608 --- /dev/null +++ b/WorterBuch/SelectableTextView.swift @@ -0,0 +1,36 @@ +// +// SelectableTextView.swift +// WorterBuch +// +// Created by Oliver Hnát on 01.12.2025. +// + +import SwiftUI +import UIKit + +struct SelectableTextView: UIViewRepresentable { + let text: String + let font: UIFont + let textColor: UIColor + + func makeUIView(context: Context) -> UITextView { + let textView = UITextView() + textView.isEditable = false + textView.isSelectable = true + textView.isScrollEnabled = false + textView.backgroundColor = .clear + textView.textContainerInset = .zero + textView.textContainer.lineFragmentPadding = 0 + textView.textContainer.maximumNumberOfLines = 2 + textView.textContainer.lineBreakMode = .byTruncatingTail + textView.dataDetectorTypes = [] + + return textView + } + + func updateUIView(_ textView: UITextView, context: Context) { + textView.text = text + textView.font = font + textView.textColor = textColor + } +} diff --git a/WorterBuch/VocabularyFieldCell.swift b/WorterBuch/VocabularyFieldCell.swift index 62e1140..dac81ab 100644 --- a/WorterBuch/VocabularyFieldCell.swift +++ b/WorterBuch/VocabularyFieldCell.swift @@ -12,36 +12,49 @@ struct VocabularyFieldCell: View { let drawing: PKDrawing let text: String let onTap: () -> Void - let onLongPress: () -> Void var body: some View { VStack(alignment: .leading, spacing: 4) { - // Handwriting preview - if !drawing.bounds.isEmpty { - Image(uiImage: drawing.image(from: drawing.bounds, scale: 2.0)) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(height: 60) - .frame(maxWidth: .infinity) - .background(Color(.systemGray6)) - } else { - Rectangle() - .fill(Color(.systemGray6)) - .frame(height: 60) - .overlay( - Text("Tap to write") - .font(.caption) - .foregroundColor(.secondary) - ) + // Handwriting preview - tappable to edit + Group { + if !drawing.bounds.isEmpty { + Image(uiImage: drawing.image(from: drawing.bounds, scale: 2.0)) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(height: 60) + .frame(maxWidth: .infinity) + .background(Color(.systemGray6)) + } else { + Rectangle() + .fill(Color(.systemGray6)) + .frame(height: 60) + .overlay( + Text("Tap to write") + .font(.caption) + .foregroundColor(.secondary) + ) + } + } + .contentShape(Rectangle()) + .onTapGesture { + onTap() } - // Transcribed text - Text(text.isEmpty ? " " : text.lowercased()) - .font(.body) - .foregroundColor(.primary) - .lineLimit(2) + // Transcribed text - selectable but not editable + if !text.isEmpty { + SelectableTextView( + text: text.lowercased(), + font: .preferredFont(forTextStyle: .body), + textColor: .label + ) .frame(maxWidth: .infinity, alignment: .leading) .frame(height: 40) + } else { + Text(" ") + .font(.body) + .frame(maxWidth: .infinity, alignment: .leading) + .frame(height: 40) + } } .padding(8) .background(Color(.systemBackground)) @@ -50,12 +63,5 @@ struct VocabularyFieldCell: View { RoundedRectangle(cornerRadius: 8) .stroke(Color.gray.opacity(0.2), lineWidth: 1) ) - .contentShape(Rectangle()) - .onTapGesture { - onTap() - } - .onLongPressGesture { - onLongPress() - } } } diff --git a/WorterBuch/VocabularyGridView.swift b/WorterBuch/VocabularyGridView.swift index f0f22c7..a341778 100644 --- a/WorterBuch/VocabularyGridView.swift +++ b/WorterBuch/VocabularyGridView.swift @@ -85,13 +85,11 @@ struct VocabularyGridView: View { entry: entry, onSelectField: { fieldType in openFieldEditor(for: entry, fieldType: fieldType) - }, - onLongPress: { fieldType in - showDefinition(for: entry, fieldType: fieldType) } ) .listRowInsets(EdgeInsets(top: 6, leading: 12, bottom: 6, trailing: 12)) .listRowSeparator(.hidden) + .listRowBackground(Color.clear) .swipeActions(edge: .trailing, allowsFullSwipe: true) { Button(role: .destructive) { deleteEntry(entry) @@ -102,6 +100,7 @@ struct VocabularyGridView: View { } } .listStyle(.plain) + .environment(\.defaultMinListRowHeight, 0) } .navigationTitle("Wörterbuch") .toolbar { @@ -201,28 +200,11 @@ struct VocabularyGridView: View { print("Error saving context: \(nsError), \(nsError.userInfo)") } } - - private func showDefinition(for entry: VocabularyEntry, fieldType: FieldType) { - let text: String - switch fieldType { - case .germanWord: - text = entry.germanWordText ?? "" - case .germanExplanation: - text = entry.germanExplanationText ?? "" - case .englishTranslation: - text = entry.englishTranslationText ?? "" - } - - if !text.isEmpty { - DictionaryHelper.showDefinition(for: text) - } - } } struct VocabularyEntryRow: View { @ObservedObject var entry: VocabularyEntry let onSelectField: (FieldType) -> Void - let onLongPress: (FieldType) -> Void var body: some View { HStack(spacing: 12) { @@ -230,8 +212,7 @@ struct VocabularyEntryRow: View { VocabularyFieldCell( drawing: entry.germanWordPKDrawing, text: entry.germanWordText ?? "", - onTap: { onSelectField(.germanWord) }, - onLongPress: { onLongPress(.germanWord) } + onTap: { onSelectField(.germanWord) } ) .frame(maxWidth: .infinity) @@ -239,8 +220,7 @@ struct VocabularyEntryRow: View { VocabularyFieldCell( drawing: entry.germanExplanationPKDrawing, text: entry.germanExplanationText ?? "", - onTap: { onSelectField(.germanExplanation) }, - onLongPress: { onLongPress(.germanExplanation) } + onTap: { onSelectField(.germanExplanation) } ) .frame(maxWidth: .infinity) @@ -248,8 +228,7 @@ struct VocabularyEntryRow: View { VocabularyFieldCell( drawing: entry.englishTranslationPKDrawing, text: entry.englishTranslationText ?? "", - onTap: { onSelectField(.englishTranslation) }, - onLongPress: { onLongPress(.englishTranslation) } + onTap: { onSelectField(.englishTranslation) } ) .frame(maxWidth: .infinity) }