From e4f939a52a4138badc67b893db0e6d26a0d90171 Mon Sep 17 00:00:00 2001 From: Prince Yadav <66916296+prince-0408@users.noreply.github.com> Date: Wed, 1 Apr 2026 23:50:19 +0530 Subject: [PATCH] feat(keyboard): add haptic feedback toggle in keyboard sub-settings #638 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add hapticFeedback case to UserInteractiveState enum - Add 'Haptic feedback' toggle to Functionality section in languageSettingsData (keyboard sub-settings page, not main settings) - Handle save/load of langCode+HapticFeedback UserDefaults key in InfoChildTableViewCell (switchDidChange + fetchSwitchStateForCell) - Add hapticFeedbackIsEnabled() in KeyboardViewController reading from shared UserDefaults container - Guard haptic block behind hapticFeedbackIsEnabled() — off by default - Strings hard-coded for now pending Scribe-i18n entry --- .../KeyboardViewController.swift | 35 +++++++++++++++++++ Scribe/ParentTableCellModel.swift | 1 + Scribe/SettingsTab/SettingsTableData.swift | 6 ++++ .../InfoChildTableViewCell.swift | 12 +++++++ 4 files changed, 54 insertions(+) diff --git a/Keyboards/KeyboardsBase/KeyboardViewController.swift b/Keyboards/KeyboardsBase/KeyboardViewController.swift index 61dfee62..89c41058 100644 --- a/Keyboards/KeyboardsBase/KeyboardViewController.swift +++ b/Keyboards/KeyboardsBase/KeyboardViewController.swift @@ -1982,6 +1982,15 @@ class KeyboardViewController: UIInputViewController { } } + func hapticFeedbackIsEnabled() -> Bool { + let langCode = languagesAbbrDict[controllerLanguage] ?? "unknown" + if let userDefaults = UserDefaults(suiteName: "group.be.scri.userDefaultsContainer") { + let dictionaryKey = langCode + "HapticFeedback" + return userDefaults.bool(forKey: dictionaryKey) + } + return false // default off + } + // MARK: Button Actions /// Triggers actions based on the press of a key. @@ -2542,6 +2551,32 @@ class KeyboardViewController: UIInputViewController { } else { sender.backgroundColor = keyPressedColor } + + // Haptic feedback on key press. + // Heavy: destructive/dismiss actions. + // Medium: command, navigation, and action keys. + // Light: all regular character keys. + guard hapticFeedbackIsEnabled() else { return } + let heavyKeys = ["delete", "hideKeyboard"] + let mediumKeys = [ + "shift", "return", "Translate", "Conjugate", "Plural", + "AutoAction0", "AutoAction1", "AutoAction2", + "EmojiKey0", "EmojiKey1", "EmojiKey2", + "GetAnnotationInfo", "ScribeAnnotation", + "shiftFormsDisplayLeft", "shiftFormsDisplayRight", + "ABC", "АБВ", "123", "#+=", ".?123", "selectKeyboard", + SpecialKeys.indent, SpecialKeys.capsLock, + spaceBar, languageTextForSpaceBar + ] + let style: UIImpactFeedbackGenerator.FeedbackStyle + if heavyKeys.contains(originalKey) { + style = .heavy + } else if mediumKeys.contains(originalKey) { + style = .medium + } else { + style = .light + } + UIImpactFeedbackGenerator(style: style).impactOccurred() } /// Shows the conjugation view for verbs. diff --git a/Scribe/ParentTableCellModel.swift b/Scribe/ParentTableCellModel.swift index 1c87cfea..8e494492 100644 --- a/Scribe/ParentTableCellModel.swift +++ b/Scribe/ParentTableCellModel.swift @@ -71,6 +71,7 @@ enum UserInteractiveState { case toggleAccentCharacters case toggleWordForWordDeletion case increaseTextSize + case hapticFeedback case none } diff --git a/Scribe/SettingsTab/SettingsTableData.swift b/Scribe/SettingsTab/SettingsTableData.swift index cfbe92d8..9494e334 100644 --- a/Scribe/SettingsTab/SettingsTableData.swift +++ b/Scribe/SettingsTab/SettingsTableData.swift @@ -153,6 +153,12 @@ enum SettingsTableData { value: "Delete text word by word when the delete key is pressed and held.", comment: "" ) + ), + Section( + sectionTitle: "Haptic feedback", + hasToggle: true, + sectionState: .none(.hapticFeedback), + shortDescription: "Enable haptic feedback on key press." ) ], hasDynamicData: nil diff --git a/Scribe/Views/Cells/InfoChildTableViewCell/InfoChildTableViewCell.swift b/Scribe/Views/Cells/InfoChildTableViewCell/InfoChildTableViewCell.swift index 5af6de00..645fc043 100644 --- a/Scribe/Views/Cells/InfoChildTableViewCell/InfoChildTableViewCell.swift +++ b/Scribe/Views/Cells/InfoChildTableViewCell/InfoChildTableViewCell.swift @@ -158,6 +158,10 @@ final class InfoChildTableViewCell: UITableViewCell { let dictionaryKey = languageCode + "WordForWordDeletion" userDefaults.setValue(toggleSwitch.isOn, forKey: dictionaryKey) + case .hapticFeedback: + let dictionaryKey = languageCode + "HapticFeedback" + userDefaults.setValue(toggleSwitch.isOn, forKey: dictionaryKey) + case .increaseTextSize: userDefaults.setValue(toggleSwitch.isOn, forKey: "increaseTextSize") initializeFontSize() @@ -211,6 +215,14 @@ final class InfoChildTableViewCell: UITableViewCell { toggleSwitch.isOn = false // default off } + case .hapticFeedback: + let dictionaryKey = languageCode + "HapticFeedback" + if let toggleValue = userDefaults.object(forKey: dictionaryKey) as? Bool { + toggleSwitch.isOn = toggleValue + } else { + toggleSwitch.isOn = false // default off + } + case .increaseTextSize: if let toggleValue = userDefaults.object(forKey: "increaseTextSize") as? Bool { toggleSwitch.isOn = toggleValue