From 532bb30c6a6fd2d4c14bba7785611564f39e20af Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 11 Jan 2026 18:32:23 +0800 Subject: [PATCH] :sparkles: Sfx on notification --- assets/audio/notification.mp3 | Bin 0 -> 45562 bytes lib/services/notify.universal.dart | 11 ++++++ lib/services/notify.windows.dart | 25 +++++++++++--- macos/Flutter/GeneratedPluginRegistrant.swift | 4 +++ macos/Podfile.lock | 13 +++++++ pubspec.lock | 32 ++++++++++++++++++ pubspec.yaml | 2 ++ 7 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 assets/audio/notification.mp3 diff --git a/assets/audio/notification.mp3 b/assets/audio/notification.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..aa68cb30fa7b2597fdf2344f629b6b7e6406918e GIT binary patch literal 45562 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 Q+rPW_2Y&9J;eA&4UjVS#o&W#< literal 0 HcmV?d00001 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