Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand Down
47 changes: 46 additions & 1 deletion Keyboards/KeyboardsBase/KeyboardViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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!
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var previousWord = ""
var currentPrefix = ""
var pastStringInTextProxy = ""
var backspaceTimer: Timer?
var longPressOnDelete: Bool = false

var baseAutosuggestions = [String]()
var completionWords = [String]()
Expand Down
1 change: 1 addition & 0 deletions Scribe/ParentTableCellModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ enum UserInteractiveState {
case doubleSpacePeriods
case autosuggestEmojis
case toggleAccentCharacters
case toggleWordForWordDeletion
case none
}

Expand Down
6 changes: 6 additions & 0 deletions Scribe/SettingsTab/SettingsTableData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}
}
Expand Down
Loading