mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-12-23 15:40:37 +00:00
Clean up HapticManager (#678)
* Check for haptic capabilities
* Make manager do most of work
* ABC enum
* Fix spelling 😊
* Small tweak
This commit is contained in:
parent
2f5e170983
commit
90ec3d419c
10 changed files with 60 additions and 63 deletions
|
@ -140,9 +140,7 @@ struct IceCubesApp: App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectedTab = newTab
|
selectedTab = newTab
|
||||||
if userPreferences.hapticTabSelectionEnabled {
|
HapticManager.shared.fireHaptic(of: .tabSelection)
|
||||||
HapticManager.shared.selectionChanged()
|
|
||||||
}
|
|
||||||
})) {
|
})) {
|
||||||
ForEach(availableTabs) { tab in
|
ForEach(availableTabs) { tab in
|
||||||
tab.makeContentView(popToRootTab: $popToRootTab)
|
tab.makeContentView(popToRootTab: $popToRootTab)
|
||||||
|
|
|
@ -102,9 +102,11 @@ struct SettingsTabs: View {
|
||||||
NavigationLink(destination: DisplaySettingsView()) {
|
NavigationLink(destination: DisplaySettingsView()) {
|
||||||
Label("settings.general.display", systemImage: "paintpalette")
|
Label("settings.general.display", systemImage: "paintpalette")
|
||||||
}
|
}
|
||||||
NavigationLink(destination: HapticSettingsView()) {
|
if HapticManager.shared.supportsHaptics {
|
||||||
Label("settings.general.haptic", systemImage: "waveform.path")
|
NavigationLink(destination: HapticSettingsView()) {
|
||||||
}
|
Label("settings.general.haptic", systemImage: "waveform.path")
|
||||||
|
}
|
||||||
|
}
|
||||||
NavigationLink(destination: remoteLocalTimelinesView) {
|
NavigationLink(destination: remoteLocalTimelinesView) {
|
||||||
Label("settings.general.remote-timelines", systemImage: "dot.radiowaves.right")
|
Label("settings.general.remote-timelines", systemImage: "dot.radiowaves.right")
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,7 @@ public struct AppAccountsSelectorView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||||
HapticManager.shared.impact()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
refreshAccounts()
|
refreshAccounts()
|
||||||
|
@ -80,9 +78,7 @@ public struct AppAccountsSelectorView: View {
|
||||||
appAccounts.currentAccount = viewModel.appAccount
|
appAccounts.currentAccount = viewModel.appAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||||
HapticManager.shared.impact()
|
|
||||||
}
|
|
||||||
} label: {
|
} label: {
|
||||||
HStack {
|
HStack {
|
||||||
if viewModel.account?.id == currentAccount.account?.id {
|
if viewModel.account?.id == currentAccount.account?.id {
|
||||||
|
@ -96,9 +92,7 @@ public struct AppAccountsSelectorView: View {
|
||||||
if accountCreationEnabled {
|
if accountCreationEnabled {
|
||||||
Divider()
|
Divider()
|
||||||
Button {
|
Button {
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||||
HapticManager.shared.impact()
|
|
||||||
}
|
|
||||||
routerPath.presentedSheet = .addAccount
|
routerPath.presentedSheet = .addAccount
|
||||||
} label: {
|
} label: {
|
||||||
Label("app-account.button.add", systemImage: "person.badge.plus")
|
Label("app-account.button.add", systemImage: "person.badge.plus")
|
||||||
|
@ -108,9 +102,7 @@ public struct AppAccountsSelectorView: View {
|
||||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||||
Divider()
|
Divider()
|
||||||
Button {
|
Button {
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||||
HapticManager.shared.impact()
|
|
||||||
}
|
|
||||||
routerPath.presentedSheet = .settings
|
routerPath.presentedSheet = .settings
|
||||||
} label: {
|
} label: {
|
||||||
Label("tab.settings", systemImage: "gear")
|
Label("tab.settings", systemImage: "gear")
|
||||||
|
|
|
@ -8,9 +8,7 @@ public extension View {
|
||||||
ToolbarItem(placement: .navigationBarTrailing) {
|
ToolbarItem(placement: .navigationBarTrailing) {
|
||||||
Button {
|
Button {
|
||||||
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
|
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||||
HapticManager.shared.impact()
|
|
||||||
}
|
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "square.and.pencil")
|
Image(systemName: "square.and.pencil")
|
||||||
}
|
}
|
||||||
|
@ -31,9 +29,7 @@ public struct StatusEditorToolbarItem: ToolbarContent {
|
||||||
ToolbarItem(placement: .navigationBarTrailing) {
|
ToolbarItem(placement: .navigationBarTrailing) {
|
||||||
Button {
|
Button {
|
||||||
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
|
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||||
HapticManager.shared.impact()
|
|
||||||
}
|
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "square.and.pencil")
|
Image(systemName: "square.and.pencil")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,57 @@
|
||||||
|
import CoreHaptics
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
public class HapticManager {
|
public class HapticManager {
|
||||||
public static let shared: HapticManager = .init()
|
public static let shared: HapticManager = .init()
|
||||||
|
|
||||||
|
public enum HapticType {
|
||||||
|
case buttonPress
|
||||||
|
case dataRefresh(intensity: CGFloat)
|
||||||
|
case notification(_ type: UINotificationFeedbackGenerator.FeedbackType)
|
||||||
|
case tabSelection
|
||||||
|
case timeline
|
||||||
|
}
|
||||||
|
|
||||||
private let selectionGenerator = UISelectionFeedbackGenerator()
|
private let selectionGenerator = UISelectionFeedbackGenerator()
|
||||||
private let impactGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
private let impactGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
||||||
private let notificationGenerator = UINotificationFeedbackGenerator()
|
private let notificationGenerator = UINotificationFeedbackGenerator()
|
||||||
|
|
||||||
|
private let userPreferences = UserPreferences.shared
|
||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
selectionGenerator.prepare()
|
selectionGenerator.prepare()
|
||||||
impactGenerator.prepare()
|
impactGenerator.prepare()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func selectionChanged() {
|
@MainActor
|
||||||
selectionGenerator.selectionChanged()
|
public func fireHaptic(of type: HapticType) {
|
||||||
|
guard supportsHaptics else { return }
|
||||||
|
|
||||||
|
switch type {
|
||||||
|
case .buttonPress:
|
||||||
|
if userPreferences.hapticButtonPressEnabled {
|
||||||
|
impactGenerator.impactOccurred()
|
||||||
|
}
|
||||||
|
case let .dataRefresh(intensity):
|
||||||
|
if userPreferences.hapticTimelineEnabled {
|
||||||
|
impactGenerator.impactOccurred(intensity: intensity)
|
||||||
|
}
|
||||||
|
case let .notification(type):
|
||||||
|
if userPreferences.hapticButtonPressEnabled {
|
||||||
|
notificationGenerator.notificationOccurred(type)
|
||||||
|
}
|
||||||
|
case .tabSelection:
|
||||||
|
if userPreferences.hapticTabSelectionEnabled {
|
||||||
|
selectionGenerator.selectionChanged()
|
||||||
|
}
|
||||||
|
case .timeline:
|
||||||
|
if userPreferences.hapticTimelineEnabled {
|
||||||
|
selectionGenerator.selectionChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func impact() {
|
public var supportsHaptics: Bool {
|
||||||
impactGenerator.impactOccurred()
|
CHHapticEngine.capabilitiesForHardware().supportsHaptics
|
||||||
}
|
|
||||||
|
|
||||||
public func impact(intensity: CGFloat) {
|
|
||||||
impactGenerator.impactOccurred(intensity: intensity)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func notification(type: UINotificationFeedbackGenerator.FeedbackType) {
|
|
||||||
notificationGenerator.notificationOccurred(type)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,9 +174,7 @@ public class StatusEditorViewModel: ObservableObject {
|
||||||
case let .edit(status):
|
case let .edit(status):
|
||||||
postStatus = try await client.put(endpoint: Statuses.editStatus(id: status.id, json: data))
|
postStatus = try await client.put(endpoint: Statuses.editStatus(id: status.id, json: data))
|
||||||
}
|
}
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .notification(.success))
|
||||||
HapticManager.shared.notification(type: .success)
|
|
||||||
}
|
|
||||||
if hasExplicitlySelectedLanguage, let selectedLanguage {
|
if hasExplicitlySelectedLanguage, let selectedLanguage {
|
||||||
preferences?.markLanguageAsSelected(isoCode: selectedLanguage)
|
preferences?.markLanguageAsSelected(isoCode: selectedLanguage)
|
||||||
}
|
}
|
||||||
|
@ -188,9 +186,7 @@ public class StatusEditorViewModel: ObservableObject {
|
||||||
showPostingErrorAlert = true
|
showPostingErrorAlert = true
|
||||||
}
|
}
|
||||||
isPosting = false
|
isPosting = false
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .notification(.error))
|
||||||
HapticManager.shared.notification(type: .error)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,9 +179,7 @@ struct StatusActionsView: View {
|
||||||
|
|
||||||
private func handleAction(action: Actions) {
|
private func handleAction(action: Actions) {
|
||||||
Task {
|
Task {
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .notification(.success))
|
||||||
HapticManager.shared.notification(type: .success)
|
|
||||||
}
|
|
||||||
switch action {
|
switch action {
|
||||||
case .respond:
|
case .respond:
|
||||||
routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.status)
|
routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.status)
|
||||||
|
|
|
@ -425,9 +425,7 @@ public struct StatusRowView: View {
|
||||||
private var trailinSwipeActions: some View {
|
private var trailinSwipeActions: some View {
|
||||||
Button {
|
Button {
|
||||||
Task {
|
Task {
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .notification(.success))
|
||||||
HapticManager.shared.notification(type: .success)
|
|
||||||
}
|
|
||||||
if viewModel.isFavorited {
|
if viewModel.isFavorited {
|
||||||
await viewModel.unFavorite()
|
await viewModel.unFavorite()
|
||||||
} else {
|
} else {
|
||||||
|
@ -440,9 +438,7 @@ public struct StatusRowView: View {
|
||||||
.tint(.yellow)
|
.tint(.yellow)
|
||||||
Button {
|
Button {
|
||||||
Task {
|
Task {
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .notification(.success))
|
||||||
HapticManager.shared.notification(type: .success)
|
|
||||||
}
|
|
||||||
if viewModel.isReblogged {
|
if viewModel.isReblogged {
|
||||||
await viewModel.unReblog()
|
await viewModel.unReblog()
|
||||||
} else {
|
} else {
|
||||||
|
@ -458,9 +454,7 @@ public struct StatusRowView: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var leadingSwipeActions: some View {
|
private var leadingSwipeActions: some View {
|
||||||
Button {
|
Button {
|
||||||
if UserPreferences.shared.hapticButtonPressEnabled {
|
HapticManager.shared.fireHaptic(of: .notification(.success))
|
||||||
HapticManager.shared.notification(type: .success)
|
|
||||||
}
|
|
||||||
routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.status)
|
routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.status)
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "arrowshape.turn.up.left")
|
Image(systemName: "arrowshape.turn.up.left")
|
||||||
|
|
|
@ -19,9 +19,7 @@ class PendingStatusesObserver: ObservableObject {
|
||||||
func removeStatus(status: Status) {
|
func removeStatus(status: Status) {
|
||||||
if !disableUpdate, let index = pendingStatuses.firstIndex(of: status.id) {
|
if !disableUpdate, let index = pendingStatuses.firstIndex(of: status.id) {
|
||||||
pendingStatuses.removeSubrange(index ... (pendingStatuses.count - 1))
|
pendingStatuses.removeSubrange(index ... (pendingStatuses.count - 1))
|
||||||
if UserPreferences.shared.hapticTimelineEnabled {
|
HapticManager.shared.fireHaptic(of: .timeline)
|
||||||
HapticManager.shared.selectionChanged()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,13 +112,9 @@ public struct TimelineView: View {
|
||||||
viewModel.isTimelineVisible = false
|
viewModel.isTimelineVisible = false
|
||||||
}
|
}
|
||||||
.refreshable {
|
.refreshable {
|
||||||
if UserPreferences.shared.hapticTimelineEnabled {
|
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.3))
|
||||||
HapticManager.shared.impact(intensity: 0.3)
|
|
||||||
}
|
|
||||||
await viewModel.fetchStatuses()
|
await viewModel.fetchStatuses()
|
||||||
if UserPreferences.shared.hapticTimelineEnabled {
|
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.7))
|
||||||
HapticManager.shared.impact(intensity: 0.7)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.onChange(of: watcher.latestEvent?.id) { _ in
|
.onChange(of: watcher.latestEvent?.id) { _ in
|
||||||
if let latestEvent = watcher.latestEvent {
|
if let latestEvent = watcher.latestEvent {
|
||||||
|
|
Loading…
Reference in a new issue