Add sound effects

This commit is contained in:
Thomas Ricouard 2023-02-28 18:55:08 +01:00
parent 6de27c62b6
commit a3e2d3f8b3
30 changed files with 109 additions and 0 deletions

View file

@ -16,6 +16,14 @@
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 */; };
9F18801229AE477F00D85459 /* tabSelection.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800A29AE477E00D85459 /* tabSelection.wav */; };
9F18801329AE477F00D85459 /* share.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800B29AE477E00D85459 /* share.wav */; };
9F18801429AE477F00D85459 /* bookmark.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800C29AE477E00D85459 /* bookmark.wav */; };
9F18801529AE477F00D85459 /* pull.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800D29AE477E00D85459 /* pull.wav */; };
9F18801629AE477F00D85459 /* refresh.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800E29AE477E00D85459 /* refresh.wav */; };
9F18801729AE477F00D85459 /* boost.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800F29AE477E00D85459 /* boost.wav */; };
9F18801829AE477F00D85459 /* favorite.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18801029AE477F00D85459 /* favorite.wav */; };
9F18801929AE477F00D85459 /* tootSent.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18801129AE477F00D85459 /* tootSent.wav */; };
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 */; };
@ -162,6 +170,14 @@
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>"; };
9664F1A8299BA5F700CBE70E /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9F18800A29AE477E00D85459 /* tabSelection.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = tabSelection.wav; sourceTree = "<group>"; };
9F18800B29AE477E00D85459 /* share.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = share.wav; sourceTree = "<group>"; };
9F18800C29AE477E00D85459 /* bookmark.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = bookmark.wav; sourceTree = "<group>"; };
9F18800D29AE477E00D85459 /* pull.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = pull.wav; sourceTree = "<group>"; };
9F18800E29AE477E00D85459 /* refresh.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = refresh.wav; sourceTree = "<group>"; };
9F18800F29AE477E00D85459 /* boost.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = boost.wav; sourceTree = "<group>"; };
9F18801029AE477F00D85459 /* favorite.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = favorite.wav; sourceTree = "<group>"; };
9F18801129AE477F00D85459 /* tootSent.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = tootSent.wav; 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>"; };
@ -387,6 +403,14 @@
9FA0D2AC29921C1F008A143B /* Embeds */ = {
isa = PBXGroup;
children = (
9F18800C29AE477E00D85459 /* bookmark.wav */,
9F18800F29AE477E00D85459 /* boost.wav */,
9F18801029AE477F00D85459 /* favorite.wav */,
9F18800D29AE477E00D85459 /* pull.wav */,
9F18800E29AE477E00D85459 /* refresh.wav */,
9F18800A29AE477E00D85459 /* tabSelection.wav */,
9F18800B29AE477E00D85459 /* share.wav */,
9F18801129AE477F00D85459 /* tootSent.wav */,
069709A3298C8545006E4CB5 /* Atkinson-Hyperlegible-Regular-102.ttf */,
069709A7298C87B5006E4CB5 /* OpenDyslexic-Regular.otf */,
9F2A542D296B1CC0009B2D7C /* glass.wav */,
@ -733,13 +757,21 @@
buildActionMask = 2147483647;
files = (
069709A5298C8545006E4CB5 /* Atkinson-Hyperlegible-Regular-102.ttf in Resources */,
9F18801329AE477F00D85459 /* share.wav in Resources */,
9F18801729AE477F00D85459 /* boost.wav in Resources */,
9F2A542C296B1177009B2D7C /* glass.caf in Resources */,
E9B576C329743F4C00BCE646 /* Localizable.strings in Resources */,
9F18801529AE477F00D85459 /* pull.wav in Resources */,
9FD34823293D06E800DB0EE9 /* Assets.xcassets in Resources */,
7429BCE2297C55D00069A946 /* Localizable.stringsdict in Resources */,
9F18801829AE477F00D85459 /* favorite.wav in Resources */,
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */,
069709A8298C87B5006E4CB5 /* OpenDyslexic-Regular.otf in Resources */,
9FAD85832971BF7200496AB1 /* Secret.plist in Resources */,
9F18801229AE477F00D85459 /* tabSelection.wav in Resources */,
9F18801429AE477F00D85459 /* bookmark.wav in Resources */,
9F18801629AE477F00D85459 /* refresh.wav in Resources */,
9F18801929AE477F00D85459 /* tootSent.wav in Resources */,
9F2A542E296B1CC0009B2D7C /* glass.wav in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;

View file

@ -175,6 +175,7 @@ struct IceCubesApp: App {
}
}
HapticManager.shared.fireHaptic(of: .tabSelection)
SoundEffectManager.shared.playSound(of: .tabSelection)
})) {
ForEach(availableTabs) { tab in
tab.makeContentView(popToRootTab: $popToRootTab)

View file

@ -69,6 +69,7 @@ struct SideBarView<Content: View>: View {
Button {
if account.id == appAccounts.currentAccount.id {
selectedTab = .profile
SoundEffectManager.shared.playSound(of: .tabSelection)
} else {
var transation = Transaction()
transation.disablesAnimations = true
@ -103,6 +104,7 @@ struct SideBarView<Content: View>: View {
}
}
selectedTab = tab
SoundEffectManager.shared.playSound(of: .tabSelection)
if tab == .notifications {
if let token = appAccounts.currentAccount.oauthToken {
userPreferences.setNotification(count: 0, token: token)

View file

@ -179,6 +179,9 @@ struct SettingsTabs: View {
Toggle(isOn: $preferences.isSocialKeyboardEnabled) {
Label("settings.other.social-keyboard", systemImage: "keyboard")
}
Toggle(isOn: $preferences.soundEffectEnabled) {
Label("settings.other.sound-effect", systemImage: "hifispeaker")
}
}
.listRowBackground(theme.primaryBackgroundColor)
}

View file

@ -152,6 +152,7 @@
"settings.section.other" = "Іншае";
"settings.other.hide-openai" = "Уключыць 🤖 памочніка";
"settings.other.social-keyboard" = "Уключыць сацыяльную клавіятуру";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Выпраўляльнік дублікатаў апавяшчэнняў";
"settings.push.duplicate.footer" = "Атрымліваеш падвоеныя апавяшчэнні? Паспрабуй гэтую чароўную кнопку каб выправіць";
"settings.push.duplicate.button.fix" = "🪄 Выправіць";

View file

@ -147,6 +147,7 @@
"settings.section.other" = "Altres opcions";
"settings.other.hide-openai" = "Activa l'ajudant 🤖";
"settings.other.social-keyboard" = "Activa el teclat social";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Solucionador de notificacions duplicades";
"settings.push.duplicate.footer" = "Rebeu les notificacions duplicades? Proveu aquest botó màgic per a solucionar-ho";
"settings.push.duplicate.button.fix" = "🪄 Soluciona-ho";

View file

@ -128,6 +128,7 @@
"settings.section.other" = "Anderes";
"settings.other.hide-openai" = "Aktiviere 🤖-Helfer";
"settings.other.social-keyboard" = "Soziale Tastatur aktivieren";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.general.content" = "Inhaltseinstellungen";
"settings.system" = "Systemeinstellungen";
"settings.content.navigation-title" = "Inhaltseinstellungen";

View file

@ -153,6 +153,7 @@
"settings.section.other" = "Other";
"settings.other.hide-openai" = "Enable 🤖 Helper";
"settings.other.social-keyboard" = "Enable Social Keyboard";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Duplicate Notifications Fixer";
"settings.push.duplicate.footer" = "Receiving duplicate notifications? Try this magic button in order to fix it";
"settings.push.duplicate.button.fix" = "🪄 Fix It";

View file

@ -152,6 +152,7 @@
"settings.section.other" = "Other";
"settings.other.hide-openai" = "Enable 🤖 Helper";
"settings.other.social-keyboard" = "Enable Social Keyboard";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Duplicate Notifications Fixer";
"settings.push.duplicate.footer" = "Receiving duplicate notifications? Try this magic button in order to fix it";
"settings.push.duplicate.button.fix" = "🪄 Fix It";

View file

@ -128,6 +128,7 @@
"settings.section.other" = "Otras opciones";
"settings.other.hide-openai" = "Activar ayudante 🤖";
"settings.other.social-keyboard" = "Activar teclado social";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.general.content" = "Ajustes de contenido";
"settings.system" = "Ajustes del sistema";
"settings.content.navigation-title" = "Ajustes de contenido";

View file

@ -128,6 +128,7 @@
"settings.section.other" = "Besteak";
"settings.other.hide-openai" = "Gaitu 🤖 laguntzailea";
"settings.other.social-keyboard" = "Gaitu teklatu soziala";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.general.content" = "Edukiaren ezarpenak";
"settings.system" = "Sistemaren ezarpenak";
"settings.content.navigation-title" = "Edukiaren ezarpenak";

View file

@ -148,6 +148,7 @@
"settings.section.other" = "Autres";
"settings.other.hide-openai" = "Activer 🤖 aide";
"settings.other.social-keyboard" = "Activer le clavier social";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Correcteur de notifications en double";
"settings.push.duplicate.footer" = "Recevez-vous des notifications en double ? Essayez ce bouton magique pour résoudre le problème";
"settings.push.duplicate.button.fix" = "🪄 Résoudre";

View file

@ -128,6 +128,7 @@
"settings.section.other" = "Altro";
"settings.other.hide-openai" = "Abilita l'aiuto del 🤖";
"settings.other.social-keyboard" = "Abilita social keyboard";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.general.content" = "Impostazioni dei contenuti";
"settings.system" = "Vai alle impostazioni di sistema";
"settings.content.navigation-title" = "Impostazioni dei contenuti";

View file

@ -152,6 +152,7 @@
"settings.section.other" = "その他";
"settings.other.hide-openai" = "AI支援機能の有効化";
"settings.other.social-keyboard" = "ソーシャルメディア向けキーボードの有効化";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "重複通知修正ツール";
"settings.push.duplicate.footer" = "重複して通知を受け取っていませんか?修正するためにこの魔法のボタンを試してみて";
"settings.push.duplicate.button.fix" = "🪄 修正する";

View file

@ -148,6 +148,7 @@
"settings.section.other" = "기타";
"settings.other.hide-openai" = "글 작성 도우미 🤖";
"settings.other.social-keyboard" = "SNS 키보드";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "중복 알림 해결사";
"settings.push.duplicate.footer" = "같은 알림이 여러 번 오나요? 위에 있는 버튼을 누르면 마법처럼 해결될 거에요.";
"settings.push.duplicate.button.fix" = "🪄 고치기";

View file

@ -152,6 +152,7 @@
"settings.section.other" = "Annet";
"settings.other.hide-openai" = "Aktiver 🤖-hjelper";
"settings.other.social-keyboard" = "Aktiver sosialt tastatur";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Reparasjon av dupliserte varslinger";
"settings.push.duplicate.footer" = "Får du dupliserte varsler? Prøv denne magiske knappen for å fikse det.";
"settings.push.duplicate.button.fix" = "🪄 Fiks det";

View file

@ -128,6 +128,7 @@
"settings.section.other" = "Overig";
"settings.other.hide-openai" = "Gebruik 🤖-hulp";
"settings.other.social-keyboard" = "Gebruik socialmedia-toetsenbord";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.general.content" = "Inhoud";
"settings.system" = "Systeeminstellingen";
"settings.content.navigation-title" = "Inhoud";

View file

@ -148,6 +148,7 @@
"settings.section.other" = "Inne";
"settings.other.hide-openai" = "Włącz 🤖 pomocnik";
"settings.other.social-keyboard" = "Włącz klawiaturę społecznościową";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Korektor duplikatów powiadomień";
"settings.push.duplicate.footer" = "Otrzymujesz zduplikowane powiadomienia? Spróbuj tego magicznego przycisku, aby to naprawić";
"settings.push.duplicate.button.fix" = "🪄 Napraw to";

View file

@ -148,6 +148,7 @@
"settings.section.other" = "Outros";
"settings.other.hide-openai" = "Habilitar 🤖 ajudante";
"settings.other.social-keyboard" = "Habilitar Teclado Social";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Corretor de notificações duplicadas";
"settings.push.duplicate.footer" = "Recebendo notificações duplicadas? Tente este botão mágico para tentar corrigir";
"settings.push.duplicate.button.fix" = "🪄 Corrigir";

View file

@ -148,6 +148,7 @@
"settings.section.other" = "Diğer";
"settings.other.hide-openai" = "Yardımcıyı 🤖 Aktive Et";
"settings.other.social-keyboard" = "Sosyal Klavyeyi Aktive Et";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Duplicate notifications fixer";
"settings.push.duplicate.footer" = "Receiving duplicate notifications? Try this magic button in order to fix it";
"settings.push.duplicate.button.fix" = "🪄 Fix it";

View file

@ -152,6 +152,7 @@
"settings.section.other" = "Інше";
"settings.other.hide-openai" = "Увімкнути 🤖 помічника";
"settings.other.social-keyboard" = "Увімкнути Social Keyboard";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.push.duplicate.title" = "Виправити задвоєння сповіщень";
"settings.push.duplicate.footer" = "Отримуєте сповіщення двічі? Спробуйте цю чарівну кнопку, щоб виправити це!";
"settings.push.duplicate.button.fix" = "🪄 Виправити!";

View file

@ -128,6 +128,7 @@
"settings.section.other" = "其他";
"settings.other.hide-openai" = "启用写作助手 🤖";
"settings.other.social-keyboard" = "启用社交键盘";
"settings.other.sound-effect" = "Enable Sound Effects";
"settings.general.content" = "内容设置";
"settings.system" = "系统设置";

View file

@ -101,8 +101,12 @@ public struct AccountDetailView: View {
}
.refreshable {
Task {
SoundEffectManager.shared.playSound(of: .pull)
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.3))
await viewModel.fetchAccount()
await viewModel.fetchNewestStatuses()
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.7))
SoundEffectManager.shared.playSound(of: .refresh)
}
}
.onChange(of: watcher.latestEvent?.id) { _ in

View file

@ -91,7 +91,11 @@ public struct ConversationsListView: View {
// note: this Task wrapper should not be necessary, but it reportedly crashes without it
// when refreshing on an empty list
Task {
SoundEffectManager.shared.playSound(of: .pull)
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.3))
await viewModel.fetchConversations()
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.7))
SoundEffectManager.shared.playSound(of: .refresh)
}
}
.onAppear {

View file

@ -0,0 +1,30 @@
import CoreHaptics
import UIKit
import AVKit
public class SoundEffectManager {
public static let shared: SoundEffectManager = .init()
public enum SoundEffect: String {
case pull, refresh
case tootSent
case tabSelection
case bookmark, boost, favorite, share
}
private let userPreferences = UserPreferences.shared
private var currentPlayer: AVAudioPlayer?
private init() {}
@MainActor
public func playSound(of type: SoundEffect) {
guard userPreferences.soundEffectEnabled else { return }
if let url = Bundle.main.url(forResource: type.rawValue, withExtension: "wav") {
currentPlayer = try? .init(contentsOf: url)
currentPlayer?.prepareToPlay()
currentPlayer?.play()
}
}
}

View file

@ -34,6 +34,7 @@ public class UserPreferences: ObservableObject {
@AppStorage("haptic_tab") public var hapticTabSelectionEnabled = true
@AppStorage("haptic_timeline") public var hapticTimelineEnabled = true
@AppStorage("haptic_button_press") public var hapticButtonPressEnabled = true
@AppStorage("sound_effect_enabled") public var soundEffectEnabled = true
@AppStorage("show_tab_label_iphone") public var showiPhoneTabLabel = true
@AppStorage("show_alt_text_for_media") public var showAltTextForMedia = true

View file

@ -68,7 +68,11 @@ public struct ExploreView: View {
}
.refreshable {
Task {
SoundEffectManager.shared.playSound(of: .pull)
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.3))
await viewModel.fetchTrending()
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.7))
SoundEffectManager.shared.playSound(of: .refresh)
}
}
.listStyle(.grouped)

View file

@ -64,7 +64,11 @@ public struct NotificationsListView: View {
await viewModel.fetchNotifications()
}
.refreshable {
SoundEffectManager.shared.playSound(of: .pull)
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.3))
await viewModel.fetchNotifications()
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.7))
SoundEffectManager.shared.playSound(of: .refresh)
}
.onChange(of: watcher.latestEvent?.id, perform: { _ in
if let latestEvent = watcher.latestEvent {

View file

@ -154,12 +154,16 @@ struct StatusRowActionsView: View {
switch action {
case .respond:
viewModel.routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.localStatus ?? viewModel.status)
SoundEffectManager.shared.playSound(of: .share)
case .favorite:
await statusDataController.toggleFavorite()
SoundEffectManager.shared.playSound(of: .favorite)
case .bookmark:
await statusDataController.toggleBookmark()
SoundEffectManager.shared.playSound(of: .bookmark)
case .boost:
await statusDataController.toggleReblog()
SoundEffectManager.shared.playSound(of: .boost)
default:
break
}

View file

@ -114,9 +114,11 @@ public struct TimelineView: View {
viewModel.isTimelineVisible = false
}
.refreshable {
SoundEffectManager.shared.playSound(of: .pull)
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.3))
await viewModel.pullToRefresh()
HapticManager.shared.fireHaptic(of: .dataRefresh(intensity: 0.7))
SoundEffectManager.shared.playSound(of: .refresh)
}
.onChange(of: watcher.latestEvent?.id) { _ in
if let latestEvent = watcher.latestEvent {