Add settings for haptic feedbacks

This commit is contained in:
Thomas Ricouard 2023-02-04 17:38:48 +01:00
parent 6b285cdbcf
commit 65ed2d871c
27 changed files with 183 additions and 25 deletions

View file

@ -16,6 +16,7 @@
7429BCE2297C55D00069A946 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 7429BCE4297C55D00069A946 /* Localizable.stringsdict */; };
7429BCE5297C5A750069A946 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 7429BCE4297C55D00069A946 /* Localizable.stringsdict */; };
7429BCE6297C5A750069A946 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 7429BCE4297C55D00069A946 /* Localizable.stringsdict */; };
9F1E8B47298EBCBB00609F80 /* HapticSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1E8B46298EBCBB00609F80 /* HapticSettingsView.swift */; };
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9F24EEB729360C330042359D /* Preview Assets.xcassets */; };
9F295540292B6C3400E0E81B /* Timeline in Frameworks */ = {isa = PBXBuildFile; productRef = 9F29553F292B6C3400E0E81B /* Timeline */; };
9F2A540729699698009B2D7C /* SupportAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A540629699698009B2D7C /* SupportAppView.swift */; };
@ -147,6 +148,7 @@
8C27D978298471E900CDF593 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = "<group>"; };
8C27D979298471E900CDF593 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9606B7A1297AD2BB00C1FB75 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
9F1E8B46298EBCBB00609F80 /* HapticSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticSettingsView.swift; sourceTree = "<group>"; };
9F24EEB729360C330042359D /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
9F29553D292B67B600E0E81B /* Network */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Network; path = Packages/Network; sourceTree = "<group>"; };
9F29553E292B6AF600E0E81B /* Timeline */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Timeline; path = Packages/Timeline; sourceTree = "<group>"; };
@ -441,16 +443,17 @@
9FE151A4293C90EA00E9683D /* Settings */ = {
isa = PBXGroup;
children = (
9FAE4ACA293783B000772766 /* SettingsTab.swift */,
9FE151A5293C90F900E9683D /* IconSelectorView.swift */,
9F2B92F9295DA7D700DE16D0 /* AddAccountsView.swift */,
9F2B92FB295DA94500DE16D0 /* InstanceInfoView.swift */,
9F7335F82968576500AFF0BA /* DisplaySettingsView.swift */,
9F2A540629699698009B2D7C /* SupportAppView.swift */,
9F2A5410296A1429009B2D7C /* PushNotificationsView.swift */,
C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */,
9F7D939929805DBD00EE6B7A /* AccountSettingView.swift */,
069709A9298C9AD7006E4CB5 /* AboutView.swift */,
9F7D939929805DBD00EE6B7A /* AccountSettingView.swift */,
9F2B92F9295DA7D700DE16D0 /* AddAccountsView.swift */,
C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */,
9F7335F82968576500AFF0BA /* DisplaySettingsView.swift */,
9F1E8B46298EBCBB00609F80 /* HapticSettingsView.swift */,
9FE151A5293C90F900E9683D /* IconSelectorView.swift */,
9F2B92FB295DA94500DE16D0 /* InstanceInfoView.swift */,
9F2A5410296A1429009B2D7C /* PushNotificationsView.swift */,
9FAE4ACA293783B000772766 /* SettingsTab.swift */,
9F2A540629699698009B2D7C /* SupportAppView.swift */,
);
path = Settings;
sourceTree = "<group>";
@ -744,6 +747,7 @@
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */,
9F7335F22967608F00AFF0BA /* AddRemoteTimelineView.swift in Sources */,
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */,
9F1E8B47298EBCBB00609F80 /* HapticSettingsView.swift in Sources */,
9F2A5411296A1429009B2D7C /* PushNotificationsView.swift in Sources */,
9FAD85A8297582F100496AB1 /* QuickLookRepresentable.swift in Sources */,
);

View file

@ -140,7 +140,9 @@ struct IceCubesApp: App {
}
}
selectedTab = newTab
HapticManager.shared.selectionChanged()
if userPreferences.hapticTabSelectionEnabled {
HapticManager.shared.selectionChanged()
}
})) {
ForEach(availableTabs) { tab in
tab.makeContentView(popToRootTab: $popToRootTab)

View file

@ -0,0 +1,24 @@
import DesignSystem
import Env
import Models
import Status
import SwiftUI
struct HapticSettingsView: View {
@EnvironmentObject private var theme: Theme
@EnvironmentObject private var userPreferences: UserPreferences
var body: some View {
Form {
Section {
Toggle("settings.haptic.timeline", isOn: $userPreferences.hapticTimelineEnabled)
Toggle("settings.haptic.tab-selection", isOn: $userPreferences.hapticTabSelectionEnabled)
Toggle("settings.haptic.buttons", isOn: $userPreferences.hapticButtonPressEnabled)
}
.listRowBackground(theme.primaryBackgroundColor)
}
.navigationTitle("settings.haptic.navigation-title")
.scrollContentBackground(.hidden)
.background(theme.secondaryBackgroundColor)
}
}

View file

@ -100,6 +100,9 @@ struct SettingsTabs: View {
NavigationLink(destination: DisplaySettingsView()) {
Label("settings.general.display", systemImage: "paintpalette")
}
NavigationLink(destination: HapticSettingsView()) {
Label("settings.general.haptic", systemImage: "waveform.path")
}
NavigationLink(destination: remoteLocalTimelinesView) {
Label("settings.general.remote-timelines", systemImage: "dot.radiowaves.right")
}

View file

@ -141,6 +141,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Exploreu";
"tab.federated" = "Federat";

View file

@ -139,6 +139,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
"enum.expand-media.show" = "Alle zeigen";
"enum.expand-media.hide" = "Alle ausblenden";
"enum.expand-media.hide-sensitive" = "Sensible ausblenden";

View file

@ -143,6 +143,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Explore";
"tab.federated" = "Federated";

View file

@ -139,9 +139,16 @@
"settings.other.autoplay-video" = "Auto Play Videos";
"settings.about.built-with" = "Ice Cubes is built with the following Open Source software:";
"settings.about.title" = "Ice Cubes";
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Explore";
"tab.federated" = "Federated";

View file

@ -139,6 +139,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
"enum.expand-media.show" = "Siempre";
"enum.expand-media.hide" = "Nunca";
"enum.expand-media.hide-sensitive" = "Ocultar contenido sensible";

View file

@ -142,6 +142,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Explorer";
"tab.federated" = "Fédéré";

View file

@ -142,6 +142,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Esplora";
"tab.federated" = "Federazione";

View file

@ -142,6 +142,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "エクスプローラー";
"tab.federated" = "連合";

View file

@ -142,6 +142,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "둘러보기";
"tab.federated" = "연합";

View file

@ -142,6 +142,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Utforsk";
"tab.federated" = "Federert";

View file

@ -139,6 +139,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Ontdekken";
"tab.federated" = "Gefedereerd";

View file

@ -142,6 +142,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Odkrywaj";
"tab.federated" = "Globalny";

View file

@ -142,6 +142,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Explorar";
"tab.federated" = "Linha global";

View file

@ -142,6 +142,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
// MARK: Tabs
"tab.explore" = "Keşfet";
"tab.federated" = "Birleştirilmiş";

View file

@ -137,6 +137,12 @@
"settings.account.cached-posts-%@" = "Cached posts: %@";
"settings.account.action.delete-cache" = "Clear cache";
"settings.general.haptic" = "Haptic Feedback";
"settings.haptic.navigation-title" = "Haptic Settings";
"settings.haptic.timeline" = "Timeline";
"settings.haptic.tab-selection" = "Tab Selection";
"settings.haptic.buttons" = "Button Press";
"settings.display.font" = "时间线字体";
"settings.display.font.system" = "系统";
"settings.display.font.custom" = "自定义";

View file

@ -38,7 +38,9 @@ public struct AppAccountsSelectorView: View {
}
}
.onTapGesture {
HapticManager.shared.impact()
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.impact()
}
}
.onAppear {
refreshAccounts()
@ -78,7 +80,9 @@ public struct AppAccountsSelectorView: View {
appAccounts.currentAccount = viewModel.appAccount
}
HapticManager.shared.impact()
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.impact()
}
} label: {
HStack {
if viewModel.account?.id == currentAccount.account?.id {
@ -92,7 +96,9 @@ public struct AppAccountsSelectorView: View {
if accountCreationEnabled {
Divider()
Button {
HapticManager.shared.impact()
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.impact()
}
routerPath.presentedSheet = .addAccount
} label: {
Label("app-account.button.add", systemImage: "person.badge.plus")
@ -102,7 +108,9 @@ public struct AppAccountsSelectorView: View {
if UIDevice.current.userInterfaceIdiom == .phone {
Divider()
Button {
HapticManager.shared.impact()
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.impact()
}
routerPath.presentedSheet = .settings
} label: {
Label("tab.settings", systemImage: "gear")

View file

@ -8,7 +8,9 @@ public extension View {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
HapticManager.shared.impact()
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.impact()
}
} label: {
Image(systemName: "square.and.pencil")
}
@ -29,7 +31,9 @@ public struct StatusEditorToolbarItem: ToolbarContent {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
HapticManager.shared.impact()
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.impact()
}
} label: {
Image(systemName: "square.and.pencil")
}

View file

@ -31,6 +31,10 @@ public class UserPreferences: ObservableObject {
@AppStorage("suppress_dupe_reblogs") public var suppressDupeReblogs: Bool = false
@AppStorage("inAppBrowserReaderView") public var inAppBrowserReaderView = false
@AppStorage("haptic_tab") public var hapticTabSelectionEnabled = true
@AppStorage("haptic_timeline") public var hapticTimelineEnabled = true
@AppStorage("haptic_button_press") public var hapticButtonPressEnabled = true
public var postVisibility: Models.Visibility {
if useInstanceContentSettings {

View file

@ -155,7 +155,9 @@ public class StatusEditorViewModel: ObservableObject {
case let .edit(status):
postStatus = try await client.put(endpoint: Statuses.editStatus(id: status.id, json: data))
}
HapticManager.shared.notification(type: .success)
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.notification(type: .success)
}
if hasExplicitlySelectedLanguage, let selectedLanguage {
preferences?.markLanguageAsSelected(isoCode: selectedLanguage)
}
@ -167,7 +169,9 @@ public class StatusEditorViewModel: ObservableObject {
showPostingErrorAlert = true
}
isPosting = false
HapticManager.shared.notification(type: .error)
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.notification(type: .error)
}
return nil
}
}

View file

@ -156,7 +156,9 @@ struct StatusActionsView: View {
private func handleAction(action: Actions) {
Task {
HapticManager.shared.notification(type: .success)
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.notification(type: .success)
}
switch action {
case .respond:
routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.status)

View file

@ -425,7 +425,9 @@ public struct StatusRowView: View {
private var trailinSwipeActions: some View {
Button {
Task {
HapticManager.shared.notification(type: .success)
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.notification(type: .success)
}
if viewModel.isFavorited {
await viewModel.unFavorite()
} else {
@ -438,7 +440,9 @@ public struct StatusRowView: View {
.tint(.yellow)
Button {
Task {
HapticManager.shared.notification(type: .success)
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.notification(type: .success)
}
if viewModel.isReblogged {
await viewModel.unReblog()
} else {
@ -454,7 +458,9 @@ public struct StatusRowView: View {
@ViewBuilder
private var leadingSwipeActions: some View {
Button {
HapticManager.shared.notification(type: .success)
if UserPreferences.shared.hapticButtonPressEnabled {
HapticManager.shared.notification(type: .success)
}
routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.status)
} label: {
Image(systemName: "arrowshape.turn.up.left")

View file

@ -19,7 +19,9 @@ class PendingStatusesObserver: ObservableObject {
func removeStatus(status: Status) {
if !disableUpdate, let index = pendingStatuses.firstIndex(of: status.id) {
pendingStatuses.removeSubrange(index ... (pendingStatuses.count - 1))
HapticManager.shared.selectionChanged()
if UserPreferences.shared.hapticTimelineEnabled {
HapticManager.shared.selectionChanged()
}
}
}

View file

@ -93,9 +93,13 @@ public struct TimelineView: View {
viewModel.isTimelineVisible = false
}
.refreshable {
HapticManager.shared.impact(intensity: 0.3)
if UserPreferences.shared.hapticTimelineEnabled {
HapticManager.shared.impact(intensity: 0.3)
}
await viewModel.fetchStatuses()
HapticManager.shared.impact(intensity: 0.7)
if UserPreferences.shared.hapticTimelineEnabled {
HapticManager.shared.impact(intensity: 0.7)
}
}
.onChange(of: watcher.latestEvent?.id) { _ in
if let latestEvent = watcher.latestEvent {