Hide keyboard on tap, more robust search algorithm, option to search by dictionary word or definition
This commit is contained in:
parent
c74a2f520c
commit
0fea23b057
@ -42,6 +42,7 @@
|
|||||||
7E943A2D273211C300E7DDF4 /* Toki_Trainer.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 7E943A2B273211C300E7DDF4 /* Toki_Trainer.xcdatamodeld */; };
|
7E943A2D273211C300E7DDF4 /* Toki_Trainer.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 7E943A2B273211C300E7DDF4 /* Toki_Trainer.xcdatamodeld */; };
|
||||||
7EBAE6AA273D65FD00BCFA09 /* toki-lessons.json in Resources */ = {isa = PBXBuildFile; fileRef = 7EBAE6A9273D65FD00BCFA09 /* toki-lessons.json */; };
|
7EBAE6AA273D65FD00BCFA09 /* toki-lessons.json in Resources */ = {isa = PBXBuildFile; fileRef = 7EBAE6A9273D65FD00BCFA09 /* toki-lessons.json */; };
|
||||||
7EF546162737B8FB00537AE6 /* FlashCardResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EF546152737B8FA00537AE6 /* FlashCardResultsView.swift */; };
|
7EF546162737B8FB00537AE6 /* FlashCardResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EF546152737B8FA00537AE6 /* FlashCardResultsView.swift */; };
|
||||||
|
E1A8B364290B905600B53385 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A8B363290B905600B53385 /* ViewExtensions.swift */; };
|
||||||
E1D79AE328EC396200A104BF /* DictionaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D79AE228EC396200A104BF /* DictionaryView.swift */; };
|
E1D79AE328EC396200A104BF /* DictionaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D79AE228EC396200A104BF /* DictionaryView.swift */; };
|
||||||
E1D79AE528F1914600A104BF /* TranslatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D79AE428F1914600A104BF /* TranslatorView.swift */; };
|
E1D79AE528F1914600A104BF /* TranslatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D79AE428F1914600A104BF /* TranslatorView.swift */; };
|
||||||
E1D79AE728F1925400A104BF /* TokiWordsListEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D79AE628F1925400A104BF /* TokiWordsListEntryView.swift */; };
|
E1D79AE728F1925400A104BF /* TokiWordsListEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D79AE628F1925400A104BF /* TokiWordsListEntryView.swift */; };
|
||||||
@ -104,6 +105,7 @@
|
|||||||
7E943A2C273211C300E7DDF4 /* Toki_Trainer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Toki_Trainer.xcdatamodel; sourceTree = "<group>"; };
|
7E943A2C273211C300E7DDF4 /* Toki_Trainer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Toki_Trainer.xcdatamodel; sourceTree = "<group>"; };
|
||||||
7EBAE6A9273D65FD00BCFA09 /* toki-lessons.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "toki-lessons.json"; sourceTree = "<group>"; };
|
7EBAE6A9273D65FD00BCFA09 /* toki-lessons.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "toki-lessons.json"; sourceTree = "<group>"; };
|
||||||
7EF546152737B8FA00537AE6 /* FlashCardResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashCardResultsView.swift; sourceTree = "<group>"; };
|
7EF546152737B8FA00537AE6 /* FlashCardResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashCardResultsView.swift; sourceTree = "<group>"; };
|
||||||
|
E1A8B363290B905600B53385 /* ViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtensions.swift; sourceTree = "<group>"; };
|
||||||
E1D79AE228EC396200A104BF /* DictionaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryView.swift; sourceTree = "<group>"; };
|
E1D79AE228EC396200A104BF /* DictionaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryView.swift; sourceTree = "<group>"; };
|
||||||
E1D79AE428F1914600A104BF /* TranslatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslatorView.swift; sourceTree = "<group>"; };
|
E1D79AE428F1914600A104BF /* TranslatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslatorView.swift; sourceTree = "<group>"; };
|
||||||
E1D79AE628F1925400A104BF /* TokiWordsListEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokiWordsListEntryView.swift; sourceTree = "<group>"; };
|
E1D79AE628F1925400A104BF /* TokiWordsListEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokiWordsListEntryView.swift; sourceTree = "<group>"; };
|
||||||
@ -217,6 +219,7 @@
|
|||||||
7E943A1F273211C200E7DDF4 /* Toki Trainer */ = {
|
7E943A1F273211C200E7DDF4 /* Toki Trainer */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E1A8B362290B903B00B53385 /* Extensions */,
|
||||||
7E44978E275C495E0016B6DC /* Toki Trainer.entitlements */,
|
7E44978E275C495E0016B6DC /* Toki Trainer.entitlements */,
|
||||||
7E28111E273302890063DC78 /* JSON Data */,
|
7E28111E273302890063DC78 /* JSON Data */,
|
||||||
7E281113273302530063DC78 /* ViewModels */,
|
7E281113273302530063DC78 /* ViewModels */,
|
||||||
@ -239,6 +242,14 @@
|
|||||||
path = "Preview Content";
|
path = "Preview Content";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E1A8B362290B903B00B53385 /* Extensions */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E1A8B363290B905600B53385 /* ViewExtensions.swift */,
|
||||||
|
);
|
||||||
|
path = Extensions;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E1D79AE828F1947F00A104BF /* WordListViews */ = {
|
E1D79AE828F1947F00A104BF /* WordListViews */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -394,6 +405,7 @@
|
|||||||
7E716B4227398CDF009E2CF6 /* FlashCardLessonsView.swift in Sources */,
|
7E716B4227398CDF009E2CF6 /* FlashCardLessonsView.swift in Sources */,
|
||||||
7E2811172733027F0063DC78 /* TokiDictionary.swift in Sources */,
|
7E2811172733027F0063DC78 /* TokiDictionary.swift in Sources */,
|
||||||
E1D79AE728F1925400A104BF /* TokiWordsListEntryView.swift in Sources */,
|
E1D79AE728F1925400A104BF /* TokiWordsListEntryView.swift in Sources */,
|
||||||
|
E1A8B364290B905600B53385 /* ViewExtensions.swift in Sources */,
|
||||||
7E71E6ED2735D70C007CFF72 /* FlashCardView.swift in Sources */,
|
7E71E6ED2735D70C007CFF72 /* FlashCardView.swift in Sources */,
|
||||||
7E943A21273211C200E7DDF4 /* Toki_TrainerApp.swift in Sources */,
|
7E943A21273211C200E7DDF4 /* Toki_TrainerApp.swift in Sources */,
|
||||||
7E716B462739B968009E2CF6 /* FlashCardLessonResultsView.swift in Sources */,
|
7E716B462739B968009E2CF6 /* FlashCardLessonResultsView.swift in Sources */,
|
||||||
@ -420,7 +432,7 @@
|
|||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = W9ASV855X5;
|
DEVELOPMENT_TEAM = W9ASV855X5;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = "Toki Trainer Widgets/Info.plist";
|
INFOPLIST_FILE = "Toki Trainer Widgets/Info.plist";
|
||||||
@ -431,7 +443,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "info.maddie.Toki-Trainer.Toki-Trainer-Widgets";
|
PRODUCT_BUNDLE_IDENTIFIER = "info.maddie.Toki-Trainer.Toki-Trainer-Widgets";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@ -447,7 +459,7 @@
|
|||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = W9ASV855X5;
|
DEVELOPMENT_TEAM = W9ASV855X5;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = "Toki Trainer Widgets/Info.plist";
|
INFOPLIST_FILE = "Toki Trainer Widgets/Info.plist";
|
||||||
@ -458,7 +470,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "info.maddie.Toki-Trainer.Toki-Trainer-Widgets";
|
PRODUCT_BUNDLE_IDENTIFIER = "info.maddie.Toki-Trainer.Toki-Trainer-Widgets";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@ -592,7 +604,7 @@
|
|||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = "Toki Trainer/Toki Trainer.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "Toki Trainer/Toki Trainer.entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Toki Trainer/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Toki Trainer/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = W9ASV855X5;
|
DEVELOPMENT_TEAM = W9ASV855X5;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@ -623,7 +635,7 @@
|
|||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = "Toki Trainer/Toki Trainer.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "Toki Trainer/Toki Trainer.entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Toki Trainer/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Toki Trainer/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = W9ASV855X5;
|
DEVELOPMENT_TEAM = W9ASV855X5;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
|
15
Toki Trainer/Extensions/ViewExtensions.swift
Normal file
15
Toki Trainer/Extensions/ViewExtensions.swift
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// ViewExtensions.swift
|
||||||
|
// Toki Trainer
|
||||||
|
//
|
||||||
|
// Created by maddiefuzz on 10/28/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
func hideKeyboard() {
|
||||||
|
let resign = #selector(UIResponder.resignFirstResponder)
|
||||||
|
UIApplication.shared.sendAction(resign, to: nil, from: nil, for: nil)
|
||||||
|
}
|
||||||
|
}
|
@ -52,12 +52,22 @@ class TokiDictionaryViewModel: ObservableObject {
|
|||||||
entryMatch = true
|
entryMatch = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if any part of the word definitions match in English, even partially
|
// Check if any part of the word definitions match in English, even partially, but
|
||||||
|
// only by prefix (if one of the definition words matches the beginning of the word with
|
||||||
|
// the search term)
|
||||||
for definition in value.definitions {
|
for definition in value.definitions {
|
||||||
if definition.definition.contains(input) {
|
let capturePattern = #"(\w+)"#
|
||||||
|
let captures = self.searchStringForRegex(string: definition.definition, regex: capturePattern)
|
||||||
|
for capture in captures {
|
||||||
|
if capture.hasPrefix(input) {
|
||||||
entryMatch = true
|
entryMatch = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Commented out, less strict matching that will match on any substring match
|
||||||
|
// if definition.definition.contains(input) {
|
||||||
|
// entryMatch = true
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
// Add to dictionary
|
// Add to dictionary
|
||||||
if entryMatch == true {
|
if entryMatch == true {
|
||||||
|
@ -7,11 +7,19 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
enum SearchMode {
|
||||||
|
case Dictionary
|
||||||
|
case Definitions
|
||||||
|
}
|
||||||
|
|
||||||
struct DictionaryView: View {
|
struct DictionaryView: View {
|
||||||
@ObservedObject var tokiDictViewModel = TokiDictionaryViewModel()
|
@ObservedObject var tokiDictViewModel = TokiDictionaryViewModel()
|
||||||
|
|
||||||
@State private var tokiInput: String = ""
|
@State private var tokiInput: String = ""
|
||||||
@State private var selectedPartOfSpeech: String?
|
@State private var selectedPartOfSpeech: String?
|
||||||
|
@State var searchMode: SearchMode = .Dictionary
|
||||||
|
|
||||||
|
@FocusState private var searchInputIsForuced: Bool
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
@ -21,7 +29,21 @@ struct DictionaryView: View {
|
|||||||
.disableAutocorrection(true)
|
.disableAutocorrection(true)
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.onSubmit {
|
.onSubmit {
|
||||||
tokiDictViewModel.filterDictionary(tokiInput)
|
filterByInput()
|
||||||
|
//tokiDictViewModel.filterDictionaryEnglishMode(tokiInput)
|
||||||
|
}
|
||||||
|
Picker("Language", selection: $searchMode) {
|
||||||
|
Text("Dictionary").tag(SearchMode.Dictionary)
|
||||||
|
Text("Definitions").tag(SearchMode.Definitions)
|
||||||
|
}
|
||||||
|
.pickerStyle(SegmentedPickerStyle())
|
||||||
|
.onTapGesture {
|
||||||
|
if self.searchMode == SearchMode.Dictionary {
|
||||||
|
self.searchMode = SearchMode.Definitions
|
||||||
|
} else {
|
||||||
|
self.searchMode = SearchMode.Dictionary
|
||||||
|
}
|
||||||
|
filterByInput()
|
||||||
}
|
}
|
||||||
List(tokiDictViewModel.dictionary, id: \.word) { entry in
|
List(tokiDictViewModel.dictionary, id: \.word) { entry in
|
||||||
TokiWordsListEntryView(entry: entry, selectedPartOfSpeech: $selectedPartOfSpeech)
|
TokiWordsListEntryView(entry: entry, selectedPartOfSpeech: $selectedPartOfSpeech)
|
||||||
@ -30,12 +52,25 @@ struct DictionaryView: View {
|
|||||||
PartsOfSpeechView(selectedPartOfSpeech: selectedPOS)
|
PartsOfSpeechView(selectedPartOfSpeech: selectedPOS)
|
||||||
}
|
}
|
||||||
.onChange(of: tokiInput) { newValue in
|
.onChange(of: tokiInput) { newValue in
|
||||||
tokiDictViewModel.filterDictionaryEnglishMode(newValue)
|
filterByInput()
|
||||||
|
//tokiDictViewModel.filterDictionaryEnglishMode(newValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
hideKeyboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterByInput() {
|
||||||
|
if self.searchMode == SearchMode.Dictionary {
|
||||||
|
tokiDictViewModel.filterDictionary(tokiInput)
|
||||||
|
} else {
|
||||||
|
tokiDictViewModel.filterDictionaryEnglishMode(tokiInput)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct DictionaryView_Previews: PreviewProvider {
|
struct DictionaryView_Previews: PreviewProvider {
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
|
@ -53,6 +53,9 @@ struct TranslatorView: View {
|
|||||||
.onChange(of: tokiInput) { newValue in
|
.onChange(of: tokiInput) { newValue in
|
||||||
tokiDictViewModel.translatePhrase(newValue)
|
tokiDictViewModel.translatePhrase(newValue)
|
||||||
}
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
hideKeyboard()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func changeTranslationDirection() {
|
func changeTranslationDirection() {
|
||||||
|
Loading…
Reference in New Issue
Block a user