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

View File

@@ -2,6 +2,8 @@ import "dart:async";
import "dart:convert";
import "package:flutter/material.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/pods/chat/chat_room.dart";
import "package:island/pods/lifecycle.dart";
@@ -198,7 +200,7 @@ class ChatSubscribeNotifier extends _$ChatSubscribeNotifier {
return _typingStatuses;
}
void onMessage(WebSocketPacket pkt) {
Future<void> onMessage(WebSocketPacket pkt) async {
if (!pkt.type.startsWith('messages')) return;
if (['messages.read'].contains(pkt.type)) return;
@@ -238,6 +240,17 @@ class ChatSubscribeNotifier extends _$ChatSubscribeNotifier {
_messagesNotifier.receiveMessage(message);
// Send read receipt for new message
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) {
final player = AudioPlayer();
player
.setAudioSource(
AudioSource.asset('assets/audio/notification.mp3'),
)
.then((_) {
player.play().then((_) => player.dispose());
});
await player.setVolume(0.75);
await player.setAudioSource(AudioSource.asset('assets/audio/notification.mp3'));
await player.play();
player.dispose();
}
showTopSnackBar(
globalOverlay.currentState!,

View File

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

View File

@@ -275,7 +275,8 @@ class _TaskOverlayContent extends HookConsumerWidget {
),
if (activeTasks.any(
(task) =>
task.status == DriveTaskStatus.inProgress,
task.status == DriveTaskStatus.inProgress &&
task.uploadedBytes < task.fileSize,
))
CircularProgressIndicator(
value: null, // Indeterminate
@@ -378,7 +379,8 @@ class _TaskOverlayContent extends HookConsumerWidget {
if (activeTasks.any(
(task) =>
task.status ==
DriveTaskStatus.inProgress,
DriveTaskStatus.inProgress &&
task.uploadedBytes < task.fileSize,
))
CircularProgressIndicator(
value: null, // Indeterminate
@@ -533,14 +535,9 @@ class _TaskOverlayContent extends HookConsumerWidget {
}
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 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;
}
@@ -672,14 +669,9 @@ class UploadTaskTile extends StatefulWidget {
State<UploadTaskTile> createState() => _UploadTaskTileState();
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 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;
}
}