Skip to content
This repository was archived by the owner on Dec 23, 2022. It is now read-only.

Commit 01e1301

Browse files
committed
Add haptic toggle
1 parent a5a190a commit 01e1301

9 files changed

Lines changed: 80 additions & 94 deletions

File tree

Podfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ target 'TooDoo' do
1717
pod 'ChameleonFramework/Swift'
1818
pod 'Typist'
1919
pod 'LTMorphingLabel'
20-
pod 'Haptica'
2120
pod 'Motion'
2221
pod 'BulletinBoard', :git => 'https://github.com/CaliCastle/BulletinBoard.git'
2322
pod 'Peep'

README.md

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,3 @@ _Supported devices:_
5353
- Location-sensitive notifications for to-dos
5454
- Search
5555
- iPad & Landscape orientation support
56-
57-
---
58-
59-
### Open source libraries:
60-
- M13Checkbox
61-
- ChameleonFramework
62-
- Typist
63-
- LTMorphingLabel
64-
- Haptica
65-
- Motion
66-
- BulletinBoard
67-
- Peep
68-
- ViewAnimator
69-
- Hokusai
70-
- DeckTransition
71-
- NotificationBannerSwift
72-
- DateTimePicker
73-

TooDoo.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@
152152
9D3E9760207C7BA80044E9F8 /* +UIScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3E975F207C7BA80044E9F8 /* +UIScrollView.swift */; };
153153
9D3E9762207CA03D0044E9F8 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D3E9761207CA03D0044E9F8 /* Colors.xcassets */; };
154154
9D3E9764207CA6750044E9F8 /* +UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3E9763207CA6750044E9F8 /* +UILabel.swift */; };
155+
9D3E9766207CC0710044E9F8 /* Haptic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3E9765207CC0710044E9F8 /* Haptic.swift */; };
155156
9DBCB22B2079BDD200A8ECF2 /* AppIconsCollectionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DBCB22A2079BDD200A8ECF2 /* AppIconsCollectionViewModel.swift */; };
156157
9DBCB22D2079F77300A8ECF2 /* AppIcons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9DBCB22C2079F77300A8ECF2 /* AppIcons.xcassets */; };
157158
9DBCB23F2079FF5D00A8ECF2 /* Side_Menu_Fade.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9DBCB23B2079FF5D00A8ECF2 /* Side_Menu_Fade.gif */; };
@@ -325,6 +326,7 @@
325326
9D3E975F207C7BA80044E9F8 /* +UIScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "+UIScrollView.swift"; sourceTree = "<group>"; };
326327
9D3E9761207CA03D0044E9F8 /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = "<group>"; };
327328
9D3E9763207CA6750044E9F8 /* +UILabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "+UILabel.swift"; sourceTree = "<group>"; };
329+
9D3E9765207CC0710044E9F8 /* Haptic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Haptic.swift; sourceTree = "<group>"; };
328330
9DBCB22A2079BDD200A8ECF2 /* AppIconsCollectionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIconsCollectionViewModel.swift; sourceTree = "<group>"; };
329331
9DBCB22C2079F77300A8ECF2 /* AppIcons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = AppIcons.xcassets; sourceTree = "<group>"; };
330332
9DBCB23B2079FF5D00A8ECF2 /* Side_Menu_Fade.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = Side_Menu_Fade.gif; sourceTree = "<group>"; };
@@ -692,6 +694,7 @@
692694
8D1F6A831FB65DC4004709E3 /* NotificationManager.swift */,
693695
8DD7CAEC1FCEB4BB00EFA73A /* LocaleManager.swift */,
694696
8D2075BF1FCFF2F100FBE622 /* PermissionManager.swift */,
697+
9D3E9765207CC0710044E9F8 /* Haptic.swift */,
695698
);
696699
path = Managers;
697700
sourceTree = "<group>";
@@ -1498,6 +1501,7 @@
14981501
8D6A139F1F93E2FC004238D8 /* UserDefaultManager.swift in Sources */,
14991502
8DAC8F861FB041F4006207F6 /* CornerRadiusView.swift in Sources */,
15001503
8D1F6A841FB65DC4004709E3 /* NotificationManager.swift in Sources */,
1504+
9D3E9766207CC0710044E9F8 /* Haptic.swift in Sources */,
15011505
8DD7CAF01FCEC68100EFA73A /* LanguageSettingsTableViewController.swift in Sources */,
15021506
8DBA55921FC430F80012B941 /* +UITextView.swift in Sources */,
15031507
8D6A13A71F93EF70004238D8 /* StoryboardManager.swift in Sources */,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Haptic.swift
3+
// TooDoo
4+
//
5+
// Created by Cali Castle on 4/10/18.
6+
// Copyright © 2018 Cali Castle . All rights reserved.
7+
//
8+
9+
import UIKit
10+
import Haptica
11+
12+
public enum Haptic {
13+
14+
case impact(UIImpactFeedbackStyle)
15+
case notification(UINotificationFeedbackType)
16+
case selection
17+
18+
// Trigger haptic generator.
19+
public func generate() {
20+
guard #available(iOS 10, *), UserDefaultManager.settingHapticsEnabled() else { return }
21+
22+
switch self {
23+
case .impact(let style):
24+
let generator = UIImpactFeedbackGenerator(style: style)
25+
generator.prepare()
26+
generator.impactOccurred()
27+
case .notification(let type):
28+
let generator = UINotificationFeedbackGenerator()
29+
generator.prepare()
30+
generator.notificationOccurred(type)
31+
case .selection:
32+
let generator = UISelectionFeedbackGenerator()
33+
generator.prepare()
34+
generator.selectionChanged()
35+
}
36+
}
37+
}

TooDoo/Library/Helpers/Managers/UserDefaultManager.swift

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ final class UserDefaultManager {
4141
case AppIconChangedWithTheme
4242
/// - The sounds option
4343
case Sounds
44+
/// - The haptics option
45+
case Haptics
4446
/// - The dark or light mode
4547
case ThemeMode
4648
/// - The motion effect animation
@@ -138,16 +140,28 @@ final class UserDefaultManager {
138140
///
139141
/// - Parameter key: The User Default key
140142
/// - Returns: Boolean result
141-
class func bool(forKey key: Key) -> Bool {
142-
return userDefaults.bool(forKey: key.rawValue)
143+
class func bool(forKey key: Key, default: Bool? = nil) -> Bool {
144+
let value = userDefaults.value(forKey: key.rawValue)
145+
146+
if let `default` = `default`, value == nil {
147+
return `default`
148+
}
149+
150+
return (value as? Bool) ?? false
143151
}
144152

145153
/// Get boolean for a User Settings key
146154
///
147155
/// - Parameter key: The User Setting key
148156
/// - Returns: Boolean result
149-
class func bool(forKey key: SettingKey) -> Bool {
150-
return userDefaults.bool(forKey: key.string())
157+
class func bool(forKey key: SettingKey, default: Bool? = nil) -> Bool {
158+
let value = userDefaults.value(forKey: key.string())
159+
160+
if let `default` = `default`, value == nil {
161+
return `default`
162+
}
163+
164+
return (value as? Bool) ?? false
151165
}
152166

153167
/// Set a value for a User Defaults key
@@ -286,7 +300,12 @@ extension UserDefaultManager {
286300

287301
/// See if sounds setting is enabled.
288302
class func settingSoundsEnabled() -> Bool {
289-
return userDefaults.value(forKey: SettingKey.Sounds.string()) == nil ? true : bool(forKey: .Sounds)
303+
return bool(forKey: .Sounds, default: true)
304+
}
305+
306+
/// See if haptics is enabled.
307+
class func settingHapticsEnabled() -> Bool {
308+
return bool(forKey: .Haptics, default: true)
290309
}
291310

292311
/// See if motion effect is enabled.

TooDoo/Resources/i18n/en.lproj/Localizable.strings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@
245245
"settings.avatar.changed" = "Avatar changed!";
246246

247247
"settings.sounds" = "Sounds";
248+
"settings.haptics" = "Haptics";
248249
"settings.motion-effects" = "Motion Effects";
249250

250251
/*

TooDoo/Resources/i18n/zh-Hans.lproj/Localizable.strings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@
244244
"settings.avatar.changed" = "头像已更改!";
245245

246246
"settings.sounds" = "音效";
247+
"settings.haptics" = "震动反馈";
247248
"settings.motion-effects" = "位移视差";
248249

249250
/*

TooDoo/Storyboards/Base.lproj/Settings.storyboard

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@
255255
</imageView>
256256
<switch opaque="NO" tag="1" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pDd-dD-FDW">
257257
<rect key="frame" x="310" y="14" width="51" height="31"/>
258+
<connections>
259+
<action selector="hapticsSwitchChanged:" destination="0DN-7j-0Ql" eventType="valueChanged" id="ucJ-OF-fug"/>
260+
</connections>
258261
</switch>
259262
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Haptics" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="v3x-Ju-E4C">
260263
<rect key="frame" x="54" y="18" width="248" height="23.666666666666671"/>
@@ -293,7 +296,7 @@
293296
<constraint firstAttribute="height" constant="30" id="EMR-Jt-zxB"/>
294297
</constraints>
295298
</imageView>
296-
<switch opaque="NO" tag="1" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HzU-0l-Xom">
299+
<switch opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HzU-0l-Xom">
297300
<rect key="frame" x="310" y="14" width="51" height="31"/>
298301
<connections>
299302
<action selector="motionEffectSwitchChanged:" destination="0DN-7j-0Ql" eventType="valueChanged" id="UoE-58-P3F"/>

TooDoo/View Controllers/Settings/SettingsTableViewController.swift

Lines changed: 9 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,11 @@ final class SettingsTableViewController: SettingTableViewController {
2424
@IBOutlet var appVersionLabel: UILabel!
2525
@IBOutlet var designedByLabel: UILabel!
2626

27-
// MARK: - Localizable Outlets.
28-
2927
/// Switch types.
30-
3128
private enum Switch: Int {
3229
case Sounds = 0
33-
case MotionEffects = 1
30+
case Haptics = 1
31+
case MotionEffects = 2
3432
}
3533

3634
// MARK: - View Life Cycle.
@@ -52,7 +50,6 @@ final class SettingsTableViewController: SettingTableViewController {
5250
}
5351

5452
/// Localize interface.
55-
5653
override func localizeInterface() {
5754
super.localizeInterface()
5855

@@ -62,7 +59,6 @@ final class SettingsTableViewController: SettingTableViewController {
6259
}
6360

6461
/// Configure app icon to be cornered.
65-
6662
fileprivate func configureAppIconImage() {
6763
appIconImageView.cornerRadius = 6
6864
appIconImageView.layer.masksToBounds = true
@@ -74,7 +70,6 @@ final class SettingsTableViewController: SettingTableViewController {
7470
}
7571

7672
/// Configure icon image views.
77-
7873
fileprivate func configureIconImages() {
7974
iconImageViews.forEach {
8075
// Bulk set image tint colors
@@ -84,13 +79,14 @@ final class SettingsTableViewController: SettingTableViewController {
8479
}
8580

8681
/// Configure switches.
87-
8882
fileprivate func configureSwitches() {
8983
switches.forEach {
9084
switch $0.tag {
9185
case Switch.Sounds.rawValue:
9286
// Sounds switch
9387
$0.setOn(UserDefaultManager.settingSoundsEnabled(), animated: false)
88+
case Switch.Haptics.rawValue:
89+
$0.setOn(UserDefaultManager.settingHapticsEnabled(), animated: false)
9490
case Switch.MotionEffects.rawValue:
9591
// Motion switch
9692
$0.setOn(UserDefaultManager.settingMotionEffectsEnabled(), animated: false)
@@ -101,7 +97,6 @@ final class SettingsTableViewController: SettingTableViewController {
10197
}
10298

10399
/// Set up table view.
104-
105100
internal override func setupTableView() {
106101
super.setupTableView()
107102

@@ -110,19 +105,16 @@ final class SettingsTableViewController: SettingTableViewController {
110105
}
111106

112107
/// Set cell labels
113-
114108
override func getCellLabels() -> [UILabel]? {
115109
return cellLabels
116110
}
117111

118112
/// Set app version text.
119-
120113
fileprivate func setVersionText() {
121114
appVersionLabel.text = Bundle.main.localizedVersionLabelString
122115
}
123116

124117
/// Set up designed and developed label.
125-
126118
fileprivate func setDesignedByText() {
127119
let text = "designed by".localized
128120
let separatedText = text.components(separatedBy: "|")
@@ -134,60 +126,27 @@ final class SettingsTableViewController: SettingTableViewController {
134126
}
135127

136128
/// Sounds switch value changed.
137-
138129
@IBAction func soundsSwitchChanged(_ sender: UISwitch) {
139130
UserDefaultManager.set(value: sender.isOn, forKey: .Sounds)
140131
}
141132

142-
/// Motion effects switch changed.
133+
/// Haptics switch changed.
134+
@IBAction func hapticsSwitchChanged(_ sender: UISwitch) {
135+
UserDefaultManager.set(value: sender.isOn, forKey: .Haptics)
136+
}
143137

138+
/// Motion effects switch changed.
144139
@IBAction func motionEffectSwitchChanged(_ sender: UISwitch) {
145140
UserDefaultManager.set(value: sender.isOn, forKey: .MotionEffects)
146141
NotificationManager.send(notification: .SettingMotionEffectsChanged)
147142
}
148143

149-
/// Authentication switch value changed.
150-
151-
@IBAction func authenticationSwitchChanged(_ sender: UISwitch) {
152-
let context = LAContext()
153-
let reason = "permission.authentication.reason".localized
154-
155-
var authError: NSError?
156-
157-
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
158-
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, evaluateError in
159-
if success {
160-
// User authenticated successfully
161-
DispatchQueue.main.async {
162-
UserDefaultManager.set(value: sender.isOn, forKey: .LockBiometric)
163-
}
164-
} else {
165-
// User did not authenticate successfully
166-
self.authenticationFailed(sender)
167-
}
168-
}
169-
} else {
170-
// Could not evaluate policy
171-
authenticationFailed(sender)
172-
}
173-
}
174-
175-
/// Set authentication switch to off state.
176-
177-
private func authenticationFailed(_ sender: UISwitch) {
178-
DispatchQueue.main.async {
179-
sender.setOn(false, animated: true)
180-
}
181-
}
182-
183144
/// When cell is about to be displayed.
184-
185145
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
186146
cell.prepareDisclosureIndicator()
187147
}
188148

189149
/// Table header titles.
190-
191150
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
192151
switch section {
193152
case 0:
@@ -201,26 +160,7 @@ final class SettingsTableViewController: SettingTableViewController {
201160
}
202161
}
203162

204-
/// Table view rows.
205-
206-
// override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
207-
// switch section {
208-
// case 0:
209-
// // Generals
210-
// return 3
211-
// case 1:
212-
// // Look & Feel
213-
// return 3
214-
// case 2:
215-
// // Privacy
216-
// return 1
217-
// default:
218-
// return 1
219-
// }
220-
// }
221-
222163
/// Prepare for segue.
223-
224164
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
225165
DispatchQueue.main.async {
226166
// Generate haptic feedback

0 commit comments

Comments
 (0)