diff --git a/assets/audio/notification.mp3 b/assets/audio/notification.mp3 new file mode 100644 index 00000000..aa68cb30 Binary files /dev/null and b/assets/audio/notification.mp3 differ diff --git a/lib/services/notify.universal.dart b/lib/services/notify.universal.dart index 8bec7108..a1abd3a9 100644 --- a/lib/services/notify.universal.dart +++ b/lib/services/notify.universal.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:io'; +import 'package:just_audio/just_audio.dart'; import 'package:dio/dio.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; @@ -104,6 +105,16 @@ StreamSubscription setupNotificationListener( if (settings.notifyWithHaptic) { HapticFeedback.heavyImpact(); } + if (settings.soundEffects) { + final player = AudioPlayer(); + player + .setAudioSource( + AudioSource.asset('assets/audio/notification.mp3'), + ) + .then((_) { + player.play().then((_) => player.dispose()); + }); + } showTopSnackBar( globalOverlay.currentState!, Center( diff --git a/lib/services/notify.windows.dart b/lib/services/notify.windows.dart index 154191f9..17dc2073 100644 --- a/lib/services/notify.windows.dart +++ b/lib/services/notify.windows.dart @@ -1,8 +1,10 @@ import 'dart:async'; import 'dart:io'; +import 'package:just_audio/just_audio.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:island/main.dart'; @@ -31,9 +33,7 @@ void _onAppLifecycleChanged(AppLifecycleState state) { Future initializeLocalNotifications() async { // Initialize Windows notification for Windows platform - windowsNotification = winty.WindowsNotification( - applicationId: "Solian", - ); + windowsNotification = winty.WindowsNotification(applicationId: "Solian"); WidgetsBinding.instance.addObserver( LifecycleEventHandler(onAppLifecycleChanged: _onAppLifecycleChanged), @@ -55,6 +55,7 @@ StreamSubscription setupNotificationListener( BuildContext context, WidgetRef ref, ) { + final settings = ref.watch(appSettingsProvider); final ws = ref.watch(websocketProvider); return ws.dataStream.listen((pkt) async { if (pkt.type == "notifications.new") { @@ -64,6 +65,19 @@ StreamSubscription setupNotificationListener( talker.info( '[Notification] Showing in-app notification: ${notification.title}', ); + if (settings.notifyWithHaptic) { + HapticFeedback.heavyImpact(); + } + if (settings.soundEffects) { + final player = AudioPlayer(); + player + .setAudioSource( + AudioSource.asset('assets/audio/notification.mp3'), + ) + .then((_) { + player.play().then((_) => player.dispose()); + }); + } showTopSnackBar( globalOverlay.currentState!, Center( @@ -139,7 +153,10 @@ StreamSubscription setupNotificationListener( final notificationMessage = NotificationMessage.fromPluginTemplate( notification.id, // unique id notification.title, - [notification.subtitle, notification.content].where((e) => e.isNotEmpty).join('\n'), + [ + notification.subtitle, + notification.content, + ].where((e) => e.isNotEmpty).join('\n'), group: notification.topic, image: imagePath, largeImage: largeImagePath, diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 4b46d52b..1d008f4e 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import audio_session import connectivity_plus import desktop_drop import device_info_plus @@ -25,6 +26,7 @@ import gal import hotkey_manager_macos import in_app_review import irondash_engine_context +import just_audio import livekit_client import local_auth_darwin import media_kit_libs_macos_video @@ -48,6 +50,7 @@ import wakelock_plus import window_manager func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) @@ -68,6 +71,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin")) + JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin")) LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 5846f7ea..b955f852 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,4 +1,6 @@ PODS: + - audio_session (0.0.1): + - FlutterMacOS - connectivity_plus (0.0.1): - FlutterMacOS - croppy (0.0.1): @@ -177,6 +179,9 @@ PODS: - FlutterMacOS - irondash_engine_context (0.0.1): - FlutterMacOS + - just_audio (0.0.1): + - Flutter + - FlutterMacOS - KeychainAccess (4.2.2) - livekit_client (2.5.4): - flutter_webrtc @@ -261,6 +266,7 @@ PODS: - FlutterMacOS DEPENDENCIES: + - audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`) - connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`) - croppy (from `Flutter/ephemeral/.symlinks/plugins/croppy/macos`) - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) @@ -283,6 +289,7 @@ DEPENDENCIES: - hotkey_manager_macos (from `Flutter/ephemeral/.symlinks/plugins/hotkey_manager_macos/macos`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) - irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`) + - just_audio (from `Flutter/ephemeral/.symlinks/plugins/just_audio/darwin`) - livekit_client (from `Flutter/ephemeral/.symlinks/plugins/livekit_client/macos`) - local_auth_darwin (from `Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin`) - media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`) @@ -330,6 +337,8 @@ SPEC REPOS: - WebRTC-SDK EXTERNAL SOURCES: + audio_session: + :path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos connectivity_plus: :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos croppy: @@ -374,6 +383,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos irondash_engine_context: :path: Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos + just_audio: + :path: Flutter/ephemeral/.symlinks/plugins/just_audio/darwin livekit_client: :path: Flutter/ephemeral/.symlinks/plugins/livekit_client/macos local_auth_darwin: @@ -418,6 +429,7 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: + audio_session: eaca2512cf2b39212d724f35d11f46180ad3a33e connectivity_plus: 4adf20a405e25b42b9c9f87feff8f4b6fde18a4e croppy: d9bfc8c02f3cd1851f669a421df298a474b78f43 desktop_drop: 10a3e6a7fa9dbe350541f2574092fecfa345a07b @@ -454,6 +466,7 @@ SPEC CHECKSUMS: hotkey_manager_macos: a4317849af96d2430fa89944d3c58977ca089fbe in_app_review: 66e7680752b632d83f4f0e88b34d52ed303fbff4 irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba + just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51 livekit_client: 3df5a1787d64010ca56c4002959d9e47c03ba3fb local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb diff --git a/pubspec.lock b/pubspec.lock index 993be289..ac76873a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -97,6 +97,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.13.0" + audio_session: + dependency: transitive + description: + name: audio_session + sha256: "8f96a7fecbb718cb093070f868b4cdcb8a9b1053dce342ff8ab2fde10eb9afb7" + url: "https://pub.dev" + source: hosted + version: "0.2.2" autotrie: dependency: transitive description: @@ -1541,6 +1549,30 @@ packages: url: "https://pub.dev" source: hosted version: "6.11.2" + just_audio: + dependency: "direct main" + description: + name: just_audio + sha256: "9694e4734f515f2a052493d1d7e0d6de219ee0427c7c29492e246ff32a219908" + url: "https://pub.dev" + source: hosted + version: "0.10.5" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + sha256: "2532c8d6702528824445921c5ff10548b518b13f808c2e34c2fd54793b999a6a" + url: "https://pub.dev" + source: hosted + version: "4.6.0" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663" + url: "https://pub.dev" + source: hosted + version: "0.4.16" leak_tracker: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c0729689..9ecfee20 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -176,6 +176,7 @@ dependencies: snow_fall_animation: ^0.0.1+3 flutter_app_intents: ^0.7.0 video_thumbnail: ^0.5.6 + just_audio: ^0.10.5 dev_dependencies: flutter_test: @@ -214,6 +215,7 @@ flutter: - assets/images/oidc/ - assets/images/stickers/ - assets/icons/ + - assets/audio/ # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images