diff --git a/CHANGELOG.md b/CHANGELOG.md index bab907c6..ffa20610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Emojis for the following are chosen based on [gitmoji](https://gitmoji.dev/). ### ✨ New Features +- Users can now delete text word for word instead of character by character by enabling a function in the settings menu. The words are deleted by holding down backspace ([#301](https://github.com/scribe-org/Scribe-iOS/issues/301)). - The Scribe translation functionality now allows the user to select which language to translate from via a convenient menu selector within the settings of each keyboard ([#255](https://github.com/scribe-org/Scribe-iOS/issues/255), [#307](https://github.com/scribe-org/Scribe-iOS/issues/307), [#469](https://github.com/scribe-org/Scribe-iOS/issues/469), [#470](https://github.com/scribe-org/Scribe-iOS/issues/470)) - The keyboard will switch to the appropriate source keyboard during translation and results will be returned from that language. - Scribe commands can now be triggered directly on a selected word by pressing the Scribe key and then choosing which command to use ([#141](https://github.com/scribe-org/Scribe-iOS/issues/141)). diff --git a/Keyboards/KeyboardsBase/KeyboardViewController.swift b/Keyboards/KeyboardsBase/KeyboardViewController.swift index 2d3f9689..97bc06b9 100644 --- a/Keyboards/KeyboardsBase/KeyboardViewController.swift +++ b/Keyboards/KeyboardsBase/KeyboardViewController.swift @@ -886,7 +886,11 @@ class KeyboardViewController: UIInputViewController { /// Deletes in the proxy or command bar given the current constraints. func handleDeleteButtonPressed() { if [.idle, .selectCommand, .alreadyPlural, .invalid].contains(commandState) { - proxy.deleteBackward() + if wordForWordDeletionIsEnabled() && longPressOnDelete { + deleteWordBackward() + } else { + proxy.deleteBackward() + } } else if [.translate, .conjugate, .plural].contains(commandState) && !(allPrompts.contains(commandBar.text ?? "") || allColoredPrompts.contains(commandBar.attributedText ?? NSAttributedString())) { guard let inputText = commandBar.text, !inputText.isEmpty else { return @@ -898,6 +902,32 @@ class KeyboardViewController: UIInputViewController { } } + func deleteWordBackward() { + guard let documentText = proxy.documentContextBeforeInput else { + return + } + + var words = documentText.split(separator: " ").map(String.init) + + guard !words.isEmpty else { + return + } + + words.removeLast() + + let updatedText = words.joined(separator: " ") + + for _ in documentText { + proxy.deleteBackward() + } + + for character in updatedText { + proxy.insertText(String(character)) + } + + proxy.adjustTextPosition(byCharacterOffset: 0) + } + // The button used to display Scribe commands and its shadow. @IBOutlet var scribeKey: ScribeKey! @IBOutlet var scribeKeyShadow: UIButton! @@ -2288,6 +2318,18 @@ class KeyboardViewController: UIInputViewController { } } + func wordForWordDeletionIsEnabled() -> Bool { + let langCode = languagesAbbrDict[controllerLanguage] ?? "unknown" + if let userDefaults = UserDefaults(suiteName: "group.be.scri.userDefaultsContainer") { + let dictionaryKey = langCode + "WordForWordDeletion" + + return userDefaults.bool(forKey: dictionaryKey) + } else { + return false // return the default value + } + + } + // MARK: Button Actions /// Triggers actions based on the press of a key. @@ -2994,6 +3036,8 @@ class KeyboardViewController: UIInputViewController { commandBar.conditionallyAddPlaceholder() } + longPressOnDelete = true + // Delete is sped up based on the number of deletes that have been completed. var deleteCount = 0 if gesture.state == .began { @@ -3019,6 +3063,7 @@ class KeyboardViewController: UIInputViewController { } else if gesture.state == .ended || gesture.state == .cancelled { backspaceTimer?.invalidate() backspaceTimer = nil + longPressOnDelete = false if let button = gesture.view as? UIButton { button.backgroundColor = specialKeyColor styleDeleteButton(button, isPressed: false) diff --git a/Keyboards/KeyboardsBase/ScribeFunctionality/CommandVariables.swift b/Keyboards/KeyboardsBase/ScribeFunctionality/CommandVariables.swift index 68a95045..7ae6d22d 100644 --- a/Keyboards/KeyboardsBase/ScribeFunctionality/CommandVariables.swift +++ b/Keyboards/KeyboardsBase/ScribeFunctionality/CommandVariables.swift @@ -32,6 +32,7 @@ var previousWord = "" var currentPrefix = "" var pastStringInTextProxy = "" var backspaceTimer: Timer? +var longPressOnDelete: Bool = false var baseAutosuggestions = [String]() var completionWords = [String]() diff --git a/Scribe/ParentTableCellModel.swift b/Scribe/ParentTableCellModel.swift index da4c28ce..3b08a1ca 100644 --- a/Scribe/ParentTableCellModel.swift +++ b/Scribe/ParentTableCellModel.swift @@ -68,6 +68,7 @@ enum UserInteractiveState { case doubleSpacePeriods case autosuggestEmojis case toggleAccentCharacters + case toggleWordForWordDeletion case none } diff --git a/Scribe/SettingsTab/SettingsTableData.swift b/Scribe/SettingsTab/SettingsTableData.swift index 5f361d33..b0d63718 100644 --- a/Scribe/SettingsTab/SettingsTableData.swift +++ b/Scribe/SettingsTab/SettingsTableData.swift @@ -72,6 +72,12 @@ enum SettingsTableData { hasToggle: true, sectionState: .none(.autosuggestEmojis), shortDescription: NSLocalizedString("app.settings.keyboard.functionality.auto_suggest_emoji_description", value: "Turn on emoji suggestions and completions for more expressive typing.", comment: "") + ), + Section( + sectionTitle: NSLocalizedString("app.word_for_word", value: "Word for word deletion on long press", comment: ""), + hasToggle: true, + sectionState: .none(.toggleWordForWordDeletion), + shortDescription: NSLocalizedString("word for word deletion", value: "Word for word deletion.", comment: "") ) ], hasDynamicData: nil diff --git a/Scribe/Views/Cells/InfoChildTableViewCell/InfoChildTableViewCell.swift b/Scribe/Views/Cells/InfoChildTableViewCell/InfoChildTableViewCell.swift index de6a7d6d..1660ecde 100644 --- a/Scribe/Views/Cells/InfoChildTableViewCell/InfoChildTableViewCell.swift +++ b/Scribe/Views/Cells/InfoChildTableViewCell/InfoChildTableViewCell.swift @@ -147,6 +147,10 @@ final class InfoChildTableViewCell: UITableViewCell { let dictionaryKey = languageCode + "EmojiAutosuggest" userDefaults.setValue(toggleSwitch.isOn, forKey: dictionaryKey) + case .toggleWordForWordDeletion: + let dictionaryKey = languageCode + "WordForWordDeletion" + userDefaults.setValue(toggleSwitch.isOn, forKey: dictionaryKey) + case .none: break } @@ -187,6 +191,14 @@ final class InfoChildTableViewCell: UITableViewCell { toggleSwitch.isOn = true // Default value } + case .toggleWordForWordDeletion: + let dictionaryKey = languageCode + "WordForWordDeletion" + if let toggleValue = userDefaults.object(forKey: dictionaryKey) as? Bool { + toggleSwitch.isOn = toggleValue + } else { + toggleSwitch.isOn = false // Default value + } + case .none: break } }