Sound effects on notifications

This commit is contained in:
2026-01-11 23:32:00 +08:00
parent 00e063e99f
commit 63a55658ab
6 changed files with 45 additions and 33 deletions

BIN
assets/audio/messages.mp3 Normal file

Binary file not shown.

View File

@@ -1,5 +1,7 @@
PODS: PODS:
- Alamofire (5.11.0) - Alamofire (5.11.0)
- audio_session (0.0.1):
- Flutter
- connectivity_plus (0.0.1): - connectivity_plus (0.0.1):
- Flutter - Flutter
- croppy (0.0.1): - croppy (0.0.1):
@@ -219,6 +221,9 @@ PODS:
- Flutter - Flutter
- irondash_engine_context (0.0.1): - irondash_engine_context (0.0.1):
- Flutter - Flutter
- just_audio (0.0.1):
- Flutter
- FlutterMacOS
- KeychainAccess (4.2.2) - KeychainAccess (4.2.2)
- Kingfisher (8.6.2) - Kingfisher (8.6.2)
- KingfisherWebP (1.7.2): - KingfisherWebP (1.7.2):
@@ -333,6 +338,7 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- Alamofire - Alamofire
- audio_session (from `.symlinks/plugins/audio_session/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- croppy (from `.symlinks/plugins/croppy/ios`) - croppy (from `.symlinks/plugins/croppy/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
@@ -357,6 +363,7 @@ DEPENDENCIES:
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`)
- irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`) - irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`)
- just_audio (from `.symlinks/plugins/just_audio/darwin`)
- Kingfisher (~> 8.0) - Kingfisher (~> 8.0)
- KingfisherWebP - KingfisherWebP
- livekit_client (from `.symlinks/plugins/livekit_client/ios`) - livekit_client (from `.symlinks/plugins/livekit_client/ios`)
@@ -418,6 +425,8 @@ SPEC REPOS:
- WebRTC-SDK - WebRTC-SDK
EXTERNAL SOURCES: EXTERNAL SOURCES:
audio_session:
:path: ".symlinks/plugins/audio_session/ios"
connectivity_plus: connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios" :path: ".symlinks/plugins/connectivity_plus/ios"
croppy: croppy:
@@ -466,6 +475,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/in_app_review/ios" :path: ".symlinks/plugins/in_app_review/ios"
irondash_engine_context: irondash_engine_context:
:path: ".symlinks/plugins/irondash_engine_context/ios" :path: ".symlinks/plugins/irondash_engine_context/ios"
just_audio:
:path: ".symlinks/plugins/just_audio/darwin"
livekit_client: livekit_client:
:path: ".symlinks/plugins/livekit_client/ios" :path: ".symlinks/plugins/livekit_client/ios"
local_auth_darwin: local_auth_darwin:
@@ -519,6 +530,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
Alamofire: bd5e7b23a1a750975288482c1831d71e74415f86 Alamofire: bd5e7b23a1a750975288482c1831d71e74415f86
audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30 croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
@@ -559,6 +571,7 @@ SPEC CHECKSUMS:
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326 image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
in_app_review: 7dd1ea365263f834b8464673f9df72c80c17c937 in_app_review: 7dd1ea365263f834b8464673f9df72c80c17c937
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486 irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed
KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51 KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
Kingfisher: 23d18f54677d973b713e54ce6a8f5eef6e7056ba Kingfisher: 23d18f54677d973b713e54ce6a8f5eef6e7056ba
KingfisherWebP: 38b9721821947f547afb78f933f75f4f9e0ae402 KingfisherWebP: 38b9721821947f547afb78f933f75f4f9e0ae402

View File

@@ -2,6 +2,8 @@ import "dart:async";
import "dart:convert"; import "dart:convert";
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:just_audio/just_audio.dart";
import "package:island/pods/config.dart";
import "package:island/models/chat.dart"; import "package:island/models/chat.dart";
import "package:island/pods/chat/chat_room.dart"; import "package:island/pods/chat/chat_room.dart";
import "package:island/pods/lifecycle.dart"; import "package:island/pods/lifecycle.dart";
@@ -198,7 +200,7 @@ class ChatSubscribeNotifier extends _$ChatSubscribeNotifier {
return _typingStatuses; return _typingStatuses;
} }
void onMessage(WebSocketPacket pkt) { Future<void> onMessage(WebSocketPacket pkt) async {
if (!pkt.type.startsWith('messages')) return; if (!pkt.type.startsWith('messages')) return;
if (['messages.read'].contains(pkt.type)) return; if (['messages.read'].contains(pkt.type)) return;
@@ -238,6 +240,17 @@ class ChatSubscribeNotifier extends _$ChatSubscribeNotifier {
_messagesNotifier.receiveMessage(message); _messagesNotifier.receiveMessage(message);
// Send read receipt for new message // Send read receipt for new message
sendReadReceipt(); sendReadReceipt();
// Play sound for new messages when app is unfocused
if (pkt.type == 'messages.new' &&
message.senderId != _chatIdentity.id &&
ref.read(appLifecycleStateProvider).value != AppLifecycleState.resumed &&
ref.read(appSettingsProvider).soundEffects) {
final player = AudioPlayer();
await player.setVolume(0.75);
await player.setAudioSource(AudioSource.asset('assets/audio/messages.mp3'));
await player.play();
player.dispose();
}
} }
} }

View File

@@ -107,13 +107,10 @@ StreamSubscription<WebSocketPacket> setupNotificationListener(
} }
if (settings.soundEffects) { if (settings.soundEffects) {
final player = AudioPlayer(); final player = AudioPlayer();
player await player.setVolume(0.75);
.setAudioSource( await player.setAudioSource(AudioSource.asset('assets/audio/notification.mp3'));
AudioSource.asset('assets/audio/notification.mp3'), await player.play();
) player.dispose();
.then((_) {
player.play().then((_) => player.dispose());
});
} }
showTopSnackBar( showTopSnackBar(
globalOverlay.currentState!, globalOverlay.currentState!,

View File

@@ -70,13 +70,10 @@ StreamSubscription<WebSocketPacket> setupNotificationListener(
} }
if (settings.soundEffects) { if (settings.soundEffects) {
final player = AudioPlayer(); final player = AudioPlayer();
player await player.setVolume(0.75);
.setAudioSource( await player.setAudioSource(AudioSource.asset('assets/audio/notification.mp3'));
AudioSource.asset('assets/audio/notification.mp3'), await player.play();
) player.dispose();
.then((_) {
player.play().then((_) => player.dispose());
});
} }
showTopSnackBar( showTopSnackBar(
globalOverlay.currentState!, globalOverlay.currentState!,

View File

@@ -275,7 +275,8 @@ class _TaskOverlayContent extends HookConsumerWidget {
), ),
if (activeTasks.any( if (activeTasks.any(
(task) => (task) =>
task.status == DriveTaskStatus.inProgress, task.status == DriveTaskStatus.inProgress &&
task.uploadedBytes < task.fileSize,
)) ))
CircularProgressIndicator( CircularProgressIndicator(
value: null, // Indeterminate value: null, // Indeterminate
@@ -378,7 +379,8 @@ class _TaskOverlayContent extends HookConsumerWidget {
if (activeTasks.any( if (activeTasks.any(
(task) => (task) =>
task.status == task.status ==
DriveTaskStatus.inProgress, DriveTaskStatus.inProgress &&
task.uploadedBytes < task.fileSize,
)) ))
CircularProgressIndicator( CircularProgressIndicator(
value: null, // Indeterminate value: null, // Indeterminate
@@ -533,14 +535,9 @@ class _TaskOverlayContent extends HookConsumerWidget {
} }
double? _getTaskProgress(DriveTask task) { double? _getTaskProgress(DriveTask task) {
if (task.status == DriveTaskStatus.completed) return 1.0; if (task.status == DriveTaskStatus.completed || (task.uploadedBytes >= task.fileSize && task.fileSize > 0)) return 1.0;
if (task.status != DriveTaskStatus.inProgress) return 0.0; if (task.status != DriveTaskStatus.inProgress) return 0.0;
// If all bytes are uploaded but still in progress, show indeterminate
if (task.uploadedBytes >= task.fileSize && task.fileSize > 0) {
return null; // Indeterminate progress
}
return task.fileSize > 0 ? task.uploadedBytes / task.fileSize : 0.0; return task.fileSize > 0 ? task.uploadedBytes / task.fileSize : 0.0;
} }
@@ -672,14 +669,9 @@ class UploadTaskTile extends StatefulWidget {
State<UploadTaskTile> createState() => _UploadTaskTileState(); State<UploadTaskTile> createState() => _UploadTaskTileState();
static double? _getTaskProgress(DriveTask task) { static double? _getTaskProgress(DriveTask task) {
if (task.status == DriveTaskStatus.completed) return 1.0; if (task.status == DriveTaskStatus.completed || (task.uploadedBytes >= task.fileSize && task.fileSize > 0)) return 1.0;
if (task.status == DriveTaskStatus.inProgress) return null; if (task.status == DriveTaskStatus.inProgress) return null;
// If all bytes are uploaded but still in progress, show indeterminate
if (task.uploadedBytes >= task.fileSize && task.fileSize > 0) {
return null; // Indeterminate progress
}
return task.fileSize > 0 ? task.uploadedBytes / task.fileSize : 0.0; return task.fileSize > 0 ? task.uploadedBytes / task.fileSize : 0.0;
} }
} }